这里是《C++ Tempaltes 2th》的读书笔记
万能引用(Universal Reference)
在模板中,存在一种万能引用模板,其参数是T&&:
| |
这种引用时可以同时接收左值和右值引用的(不像T&只能接受左值引用):
| |
当传入一个右值/右值引用时,它会将其推导为对应的引用。
| |
注意这里T的推导:被推导为int&或const int&而不是int或const int!
这个规则在转发函数参数时会造成问题:
| |
这个时候,无论t是T还是T&,t都会被视为T&,都会调用左值引用的foo函数(第一个函数)。
完美转发
要解决如上的参数转发问题,必须要使用完美转发。
完美转发会保留变量原本的特性:
- 可变变量转发后仍然可变
- const变量转发后仍然为const
- 可移动对象转发后仍然是可移动的
完美转发就一个函数:std::forward(),我们需要这么用:
| |
使用万能引用的麻烦
使用万能引用的时候,T会被视为T&,这意味着你没办法在函数体内声明非引用变量:
| |
这里由于T会被推断为int&,所以这里x的声明是错误的。
std::move
std::move说白了就是一个类似于static_cast的强制类型转换,它会将所有的类型强转到右值引用。但是其本身不会进行移动操作。
注意以下代码:
| |
这里[1]将会调用String的拷贝构造函数,这毋庸置疑。
但是[2]同时也会调用拷贝构造函数。记住,std::move只是将类型强转为右值引用,这意味着其会保留const标识,也就是说[2]中经过std::move之后的类型为const String&&,这类型和移动构造函数的类型不符,所以会调用拷贝构造函数。
std::move和std::forward的区别
他们两个本质上都是强制类型转换,只不过std::move无条件转换,而std::forward是只有参数为右值引用的时候才会转换。