Spaces in Template Expressions
The requirement to put a space between two closing template expressions has gone
1 | vector<list<int> >; // OK in each C++ version |
nullptr and std::nullptr_t
C++11 lets you use nullptr instead of 0 or NULL to specify that a pointer refers to no value (which differs from having an undefined value). This new feature especially helps to avoid mistakes that occurred when a null pointer was interpreted as an integral value. For example:
1 | void f(int); |
nullptr is a new keyword. It automatically converts into each pointer type but not to any integral type. It has type std::nullptr_t, defined in
Automatic Type Deduction with auto
With C++11, you can declare a variable or an object without specifying its specific type by using auto.
For example:
1 | auto i = 42; // i has type int |
The type of a variable declared with auto is deduced from its initializer. Thus, an initialization is required: auto i; // ERROR: can’t dedulce the type of i Additional qualifiers are allowed.
For example:
1 | static auto vat = 0.19; |
Using auto is especially useful where the type is a pretty long and/or complicated expression.
For example:
1 | vector<string> v; |
The latter is an object, representing a lambda
Uniform Initialization and Initializer Lists
Before C++11, programmers, especially novices, could easily become confused by the question of how to initialize a variable or an object. Initialization could happen with parentheses, braces, and/or assignment operators.
For this reason, C++11 introduced the concept of uniform initialization, which means that for any initialization, you can use one common syntax. This syntax uses braces, so the following is possible now:
1 | int values[] { 1, 2, 3 }; |
其实是利用一个事实:编译器看到{t1,t2…tn}便做出一个关联至一个initializer_list
std::vectorstd::string cities {“Berlin”, “New York”, “London”, “Braunschweig”, “Cairo”, “Cologne”};,这形成一个initializer_list
std::complex
这形成一个initializer_list
An initializer list forces so-called value initialization, which means that even local variables of fundamental data types, which usually have an undefined initial value, are initialized by zero (or nullptr, if it is a pointer):
1 | int i; // i has undefined value |
Note, however, that narrowing initializations — those that reduce precision or where the supplied value gets modified— are not possible with braces. For example:
1 | int x1(5.3); // OK, but OUCH: x1 becomes 5 |
To support the concept of initializer lists for user-defined types, C++11 provides the class template std::initializer_list<>. It can be used to support initializations by a list of values or in any other place where you want to process just a list of values. For example:
1 | void print (std::initializer_list<int> vals) |
cpp1.0(none explicit one argument ctor 才可以做隐式转换)
explicit for ctors taking one argument
cpp2.0
explicit for ctors taking more than one argument
range-based for statement
1 | for ( decl : coll ) { |
Note that no explicit type conversions are possible when elements are initialized as decl inside the for loop. Thus, the following does not compile:
1 | class C |
=default,=delete
如果你自行定义了一个ctor,那么编译器就不会再给你一个default ctor。
如果你强制加上=default,就可以重新获得并使用default ctor。
Alias Template ( template typedef )
1 | template<typename T> |
Type Alias (similar to typedef)
1 | //type alias,identical to |
noexcept
1 | void foo() noexcept; ==> void foo() noexcept(true); |
declares that foo() won’t throw. If an exception is not handled locally inside foo() — thus, if foo() throws — the program is terminated, calling std::terminate(), which by default calls std::abort().
You can even specify a condition under which a function throws no exception. For example, for any type Type, the global swap() usually is defined as follows:
1 | void swap (Type& x, Type& y) noexcept(noexcept(x.swap(y))) |
Here, inside noexcept(…), you can specify a Boolean condition under which no exception gets thrown: Specifying noexcept without condition is a short form of specifying noexcept(true).
https://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when-a-vector-grows
override
告诉编译器,子类要override父类的成员函数,让编译器帮助检查
1 | struce Base{ |
final
1 | struct Base1 final{}; |
decltype
By using the new decltype keyword, you can let the compiler find out the type of an expression. This is the realization of the often requested typeof feature. However, the existing typeof implementations were inconsistent and incomplete, so C++11 introduced a new keyword. For example:
GNU C++中的typeof并不是标准库的一部分
1 | map<string, float> coll; |
One application of decltype is to declare return types (see below). Another is to use it in metaprogramming (see Section 5.4.1, page 125) or to pass the type of a lambda (see Section 10.3.4, page 504).
defines a type equivalent to the type of an expression
应用:
1、decltype,used to declare return types
Sometimes, the return type of a function depends on an expression processed with the arguments.
However, something like
1 | template <typename T1, typename T2> |
was not possible before C++11, because the return expression uses objects not introduced or in scope yet.
But with C++11, you can alternatively declare the return type of a function behind the parameter list:
1 | template <typename T1, typename T2> |
This uses the same syntax as for lambdas to declare return types
[…] (…) mutable_opt throwSpec_opt ->retType_opt {…}
2、decltype, to used in metaprogramming
3、decltype, pass the type of a lambda
面对lambda,我们手上往往只有object,没有type。要获得其type就得借助于decltype。
1 | auto cmp = [](const Persion& p1, const Person& p2) { |
笔记来自 http://boolan.com/ 侯捷C++新标准C++11/14
内容引自《The C++ standard Library A Tutorial and reference》