http://en.wikipedia.org/wiki/C++0x
The modifications for C++ involve both the core language and the standard library.
修订包括内核和标准库
In the development of every utility of the 2011 standard, the committee has applied some directives:
在2011的标准中,委员会做出了如下指示:
Attention to beginners is considered important, because they will always compose the majority of computer programmers, and because many beginners would not intend to extend their knowledge of C++, limiting themselves to operate in the aspects of the language in which they are specialized.
One function of the C++ committee is the development of the language core. Areas of the core language that were significantly improved include multithreading support,generic programming support, uniform initialization, and performance enhancements.
提供了多线程支持,泛型编程支持,统一的初始化,以及性能的优化。
For the purposes of this article, core language features and changes are grouped into four general sections: run-time performance enhancements, build-time performance enhancements, usability enhancements, and new functionality. Some features could fall into multiple groups, but they are mentioned only in the group that primarily represents that feature.
核心的语言变化将分为一下四章:
These language features primarily exist to provide some kind of performance benefit, either of memory or of computational speed.
内存和cpu计算时间的优化
In C++03 (and before), temporaries (termed "rvalues", as they often lie on the right side of an assignment) were intended to never be modifiable — just as in C — and were considered to be indistinguishable from const T&
types; nevertheless, in some cases, temporaries could have been modified, a behavior that was even considered to be a useful loophole (for the former, see [7]). C++11 adds a new non-const reference type called an rvalue reference,identified by T&&
. This refers to temporaries that are permitted to be modified after they are initialized, for the purpose of allowing "move semantics".
A chronic performance problem with C++03 is the costly and unnecessary deep copies that can happen implicitly when objects are passed by value. To illustrate the issue, consider that a std::vector<T>
is, internally, a wrapper around a C-style array with a size. If a std::vector<T>
temporary is created or returned from a function, it can be stored only by creating a new std::vector<T>
and copying all of the rvalue's data into it. Then the temporary and all its memory is destroyed. (For simplicity, this discussion neglects the return value optimization).
In C++11, a "move constructor" of std::vector<T>
that takes an rvalue reference to a std::vector<T>
can copy the pointer to the internal C-style array out of the rvalue into the new std::vector<T>
, then set the pointer inside the rvalue to null. Since the temporary will never again be used, no code will try to access the null pointer, and because the pointer is null, its memory is not deleted when it goes out of scope. Hence, the operation not only forgoes the expense of a deep copy, but is safe and invisible.
Rvalue references can provide performance benefits to existing code without needing to make any changes outside the standard library. The type of the returned value of a function returning a std::vector<T>
temporary does not need to be changed explicitly to std::vector<T> &&
to invoke the move constructor, as temporaries are considered rvalues automatically. (However, if std::vector<T>
is a C++03 version without a move constructor, then the copy constructor will be invoked with a const std::vector<T>&
as normal, incurring a significant memory allocation.)
For safety reasons, some restrictions are imposed. A named variable will never be considered to be an rvalue even if it is declared as such; in order to get an rvalue, the function template std::move<T>()
should be used. Rvalue references can also be modified only under certain circumstances, being intended to be used primarily with move constructors.
Due to the nature of the wording of rvalue references, and to some modification to the wording for lvalue references (regular references), rvalue references allow developers to provide perfect function forwarding. When combined with variadic templates, this ability allows for function templates that can perfectly forward arguments to another function that takes those particular arguments. This is most useful for forwarding constructor parameters, to create factory functions that will automatically call the correct constructor for those particular arguments. This is seen in the emplace_back set of STL methods.
C++ has always had the concept of constant expressions. These are expressions such as 3+4
that will always yield the same results, at compile time and at run time. Constant expressions are optimization opportunities for compilers, and compilers frequently execute them at compile time and hardcode the results in the program. Also, there are a number of places where the C++ specification requires the use of constant expressions. Defining an array requires a constant expression, and enumerator values must be constant expressions.
However, constant expressions have always ended whenever a function call or object constructor was encountered. So a piece of code as simple as this is illegal:
int get_five() {return 5;} int some_value[get_five() + 7]; // Create an array of 12 integers. Ill-formed C++
This was not legal in C++03, because get_five() + 7
is not a constant expression. A C++03 compiler has no way of knowing if get_five()
actually is constant at runtime. In theory, this function could affect a global variable, call other non-runtime constant functions, etc.
C++11 introduced the keyword constexpr
, which allows the user to guarantee that a function or object constructor is a compile-time constant [8]. The above example can be rewritten as follows:
constexpr int get_five() {return 5;} int some_value[get_five() + 7]; // Create an array of 12 integers. Legal C++11
This allows the compiler to understand, and verify, that get_five
is a compile-time constant.
The use of constexpr
on a function imposes some limitations on what that function can do. First, the function must have a non-void return type. Second, the function body cannot declare variables or define new types. Third, the body may contain only declarations, null statements and a single return statement. There must exist argument values such that, after argument substitution, the expression in the return statement produces a constant expression.
Prior to C++11, the values of variables could be used in constant expressions only if the variables are declared const, have an initializer which is a constant expression, and are of integral or enumeration type. C++11 removes the restriction that the variables must be of integral or enumeration type if they are defined with the constexpr keyword:
constexpr double earth_gravitational_acceleration = 9.8; constexpr double moon_gravitational_acceleration = earth_gravitational_acceleration / 6.0;
Such data variables are implicitly const, and must have an initializer which must be a constant expression.
In order to construct constant expression data values from user-defined types, constructors can also be declared with constexpr
. A constexpr
constructor's function body can contain only declarations and null statements, and cannot declare variables or define types, as with a constexpr
function. There must exist argument values such that, after argument substitution, it initializes the class's members with constant expressions. The destructors for such types must be trivial.
The copy constructor for a type with any constexpr constructors should usually also be defined as a constexpr
constructor, in order to allow them to be returned by value from a constexpr function. Any member function of a class, such as copy constructors, operator overloads, etc., can be declared as constexpr
, so long as they meet the requirements for constexpr functions. This allows the compiler to copy classes at compile time, perform operations on them, etc.
If a constexpr function or constructor is called with arguments which aren't constant expressions, the call behaves as if the function were not constexpr, and the resulting value is not a constant expression. Likewise, if the expression in the return statement of a constexpr function does not evaluate to a constant expression for a particular invocation, the result is not a constant expression.