C++ 11 从C++ primer第五版的学习笔记

时间:2023-03-09 01:51:12
C++ 11 从C++ primer第五版的学习笔记
1. auto (page107)
auto 推断会忽略const
const int ci = i, & cr = ci; auto b = ci; // b is an int (top-level const in ci is dropped) auto c = cr; // c is an int (cr is an alias for ci whose const is top-level) auto d = & i; // d is an int*(& of an int object is int*) auto e = & ci; // e is const int*(& of a const object is low-level const)
如果需要推断const,需要明确加上const
const auto f = ci; // deduced type of ci is int; f has type const int
We can also specify that we want a reference to the auto-deduced type. Normal
initialization rules still apply:
; ; // ok: we can bind a const reference to a literal
When we ask for a reference to an auto-deduced type, top-level consts in the
initializer are not ignored(当我们需要引用来推断类型,top-level const在初始化时没有被忽略). As usual, consts are not top-level when we bind a reference to an initializer.
(ps:We use the term top-level const to indicate that the pointer itself is a const. When a pointer can point to a const object, we refer to that const as a low-level const.)
When we define several variables in the same statement, it is important to
remember that a reference or pointer is part of a particular declarator and not part of
the base type for the declaration. As usual, the initializers must provide consistent
auto-deduced types:
auto k = ci, &l = i; // k is int; l is int& auto &m = ci, *p = &ci; // m is a const int&;p is a pointer to const int // error: type deduced from i is int; type deduced from &ci is const int auto &n = i, *p2 = &ci;
********************************************************************************************

需要注意的是,auto不能用来声明函数的返回值。但如果函数有一个尾随的返回类型时,auto是可以出现在函数声明中返回值位置。这种情况下,auto并不是告诉编译器去推断返回类型,而是指引编译器去函数的末端寻找返回值类型。在下面这个例子中,函数的返回值类型就是operator+操作符作用在T1、T2类型变量上的返回值类型。

1
2
3
4
5
6
template <typename T1, typename T2>
auto compose(T1 t1, T2 t2) -> decltype(t1 + t2)
{
   return t1+t2;
}
auto v = compose(2, 3.14); // v's type is double
********************************************************************************************
2.decltype(page109)

返回值 decltype(表达式),表达式是不会运行的

[返回值的类型是表达式参数的类型]

decltype(f()) sum = x; // sum has whatever type f returns
decltype不会忽略 top-level const
, ; // x has type const int decltype(cj) y = x; // y has type const int& and is bound to x decltype(cj) z; // error: z is a reference and must be initialized
Some expressions willcause decltype to yield a reference type. Generally speaking, decltype returns a reference type for expressions that yield objects that can stand on the left-hand side of the assignment:(有时候表达式会导致decltype返回引用类型。一般而言,decltype返回表达式左值的引用类型)
, ) b; // ok: addition yields an int; b is an (uninitialized) int decltype(*p) c; // error: c is int& and must be initialized
r是引用类型,decltype(r)也是引用类型,但是(r+0)这个表达式返回的左值类型不是引用类型。岁b是 int类型
On the other hand, the dereference operator is an example of an expression for
which decltype returns a reference. As we’ve seen, when we dereference a pointer,
we get the object to which the pointer points. Moreover, we can assign to that object.
Thus, the type deduced by decltype(*p) is int&, not plain int. (大概意思,*操作符修饰表达式,decltype返回表达式(*p)的lvalue(参考(4)lvalue rvalue的解释),所以最后decltype(*p)是int&,而不是int)
另一个auto和decltype推断类型不同的地方是decltype还依赖给予的表达式。将变量放入小括号中将会影响decltype的返回类型。将变量放val入小括号,decltype把(val)当做表达式,这种表达式的lvalue。
//decltype of a parenthesized variable is always a reference decltype((i)) d; // error: d is int& and must be initialized,because (i) is an lvalue decltype(i) e; // ok: e is an (uninitialized) int
3.Range-Based  for Loops(page)
语法格式:
for (declaration : expression)
    statemen
expression是一个包含顺序元素的类型
遍历一个string
string str("some string"); // print the characters in str one character to a line for (auto c : str) // for every char in str cout << c << endl; // print the current character followed by a newline
string s(; // count the number of punctuation characters in s for (auto c : s) // for every char in s if (ispunct(c)) // if the character is punctuation ++punct_cnt; // increment the punctuation counter cout << punct_cnt<< " punctuation characters in " << s << endl;
这个地方似乎就感觉到了decltype的方便性了。
如果需要修改元素,需要用引用,auto& c,输出结果:HELLO WORLD!!!
string s( "Hello World!!!" ); // convert s to uppercase for ( auto & c : s) // for every char in s (note: c is a reference) c = toupper(c); // c is a reference, so the assignment changes the char in s; cout << s << endl;
Warning
The body of a range for must not change the size of the sequence over
which it is iterating.
4.模板右边括号(page142)
在C++ 98中,vector<vector<int>> vctTemp是一个非法的表达式,编译器会认为右边的>>是一个移位操作符,因此必须修改为vector<vector<int> > vctTemp,即在右边的两个>中间添加一个空格。在C++ 11中,这将不再是一个问题,编译器将能够识别出右边的双括号是两个模板参数列表的结尾。
Warning
Some compilers may require the old-style declarations for a vector of
vectors, for example, vector<vector<int> >
5.初始化列表(page143)
在引入C++ 11之前,只有数组能使用初始化列表。在C++ 11中,vector、list等各种容器以及string都可以使用初始化列表了。初始化列表对应的类为initializer_list,vector、list等各种容器以及string之所以可以使用初始化列表,是因为它们重载了参数类型为initializer_list的构造函数(称为初始化列表构造函数)和赋值函数(称为初始化列表赋值函数)。
vector , , , , }; map , }); Print({ , , , , });
getchar(); ; }
vector); }; , ); , }; // v4 has two elements with values 10 and 1

vector}; , "hi"}; // v8 has ten elements with value "hi"

虽然v5,v7,v8都有括号,但只有v5是初始化列表。我们不能用int初始化string,编译器会根据给予的值选择另一种方式初始化。
constexptr,begin(),end(),cbegin,cend,using 的typedef用法
参考
(1)C++ primer 第五版
(3)http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html C++11 新特性
(4)http://blog.chinaunix.net/uid-7471615-id-83794.html rvalue lvalue的解释