一、学习笔记
1. A a = 42; 会先以42为参数构造一个A类对象,然后调用拷贝构造函数来构造a,目前编译器优化掉了拷贝构造函数的调用,测试拷贝构造函
数是没有被调用的,但是其权限不能为private的,即使提供了重载的拷贝构造函数(其它没有调用到的构造函数可以被设置为private的)
2. 打印出下面两个地址相同,编译器优化过了
B get() { B b1(1); cout << &b1 << endl; //地址1 return b1; } int main() { B b = get(); cout << &b << endl; //地址2 return 0; }
3. C++11标准引入了右值引用,使用它可以使临时对象的拷贝具有move语意,从而可以使临时对象的拷贝具有浅拷贝般的效率,这样便可以从
一定程度上解决临时对象的深度拷贝所带来的效率折损。
4. 区分一个表达式是左值还是右值,最简便的方法就是看能不能够对它取地址:如果能,就是左值;否则,就是右值。
由于右值引用的引入,C++11标准中对表达式的分类不再是“非左即右”那么简单,不过为了简单地理解,我们暂时只需区分左值右值即可,C++11标准中的分类后面会有描述。
5. 下面简单地总结了左值引用和右值引用的绑定规则(函数类型对象会有所例外):
(1)非const左值引用只能绑定到非const左值;
(2)const左值引用可绑定到const左值、非const左值、const右值、非const右值;
(3)非const右值引用只能绑定到非const右值;
(4)const右值引用可绑定到const右值和非const右值。
6. 右值引用绑定到字面值常量同样符合上述规则,例如:int &&rr = 123;,这里的字面值123虽然被称为常量,可它的类型为int,而不是const int。对此C++03标准文档4.4.1节及其脚注中有如下说明:
7. 模板参数的推导其实就是形参和实参的比较和匹配,如果形参是一个引用类型(如P&),那么就使用P来做类型推导;如果形参是一个cv-unqualified(没有const和volatile修饰的)右值引用类型(如P&&),并且实参是一个左值(如类型A的对象),就是用A&来做类型推导(使用A&代替A)。
二、Demo
struct A { A(){} }; A rvalue() {return A();} // 返回一个非const右值对象 const A const_rvalue() {return A();} // 返回一个const右值对象 // void fun() {} // typedef decltype(fun) FUN; // typedef void FUN(); int main() { A lvalue; // 非const左值对象 const A const_lvalue; // const左值对象 // 规则一:非const左值引用只能绑定到非const左值 A &lvalue_reference1 = lvalue; // ok A &lvalue_reference2 = const_lvalue; // error A &lvalue_reference3 = rvalue(); // error A &lvalue_reference4 = const_rvalue(); // error // 规则二:const左值引用可绑定到const左值、非const左值、const右值、非const右值 const A &const_lvalue_reference1 = lvalue; // ok const A &const_lvalue_reference2 = const_lvalue; // ok const A &const_lvalue_reference3 = rvalue(); // ok const A &const_lvalue_reference4 = const_rvalue(); // ok // 规则三:非const右值引用只能绑定到非const右值 //A &&rvalue_reference1 = lvalue; // error //A &&rvalue_reference2 = const_lvalue; // error //A &&rvalue_reference3 = rvalue(); // ok //A &&rvalue_reference4 = const_rvalue(); // error // 规则四:const右值引用可绑定到const右值和非const右值,不能绑定到左值 //const A &&const_rvalue_reference1 = lvalue; // error //const A &&const_rvalue_reference2 = const_lvalue; // error //const A &&const_rvalue_reference3 = rvalue(); // ok //const A &&const_rvalue_reference4 = const_rvalue(); // ok // 规则五:函数类型例外 //FUN & lvalue_reference_to_fun = fun; // ok //const FUN & const_lvalue_reference_to_fun = fun; // ok //FUN && rvalue_reference_to_fun = fun; // ok //const FUN && const_rvalue_reference_to_fun = fun; // ok return 0; }
参考:https://www.cnblogs.com/opangle/archive/2012/11/19/2777131.html