欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

《EffectiveModernC++》学习笔记

时间:2023-06-01

T&& 有两种含义:

右值引用,只能绑定到右值上。万能引用(作者称为 “universal references” ),可以绑定到任何类型的变量上,包括左值或右值,const 或 non-const,volatile 或 non-volatile,以及以上的任何组合。

万能引用出现在两个情景中:

模板函数的参数, 形式为:

templatevoid f(T&& param); // param is a universal reference

auto 变量推导,形式为:

auto&& var2 = var1; // var2 is a universal reference

万能出现的必要条件是存在类型推导。如果看到了不存在类型推导的 T&&,那么就是右值引用,例如:

void f(Widget&& param); // no type deduction; // param is an rvalue referenceWidget&& var1 = Widget(); // no type deduction; // var1 is an rvalue reference

除了存在类型推导,万能引用还要求引用出现的形式必须为 T&&,T 不能是任何复合类型或带修饰的类型。以下例子也为右值引用而非万能引用:

templatevoid f(std::vector&& param); // param is an rvalue referencetemplatevoid f(const T&& param); // param is an rvalue reference

即使在模板函数中看到了 T&& 参数,也不能立刻敲定其为万能引用,因为在模板中不保证会存在类型推导。例如对于 STL 中的 std::vector:

template> // from C++class vector { // Standardspublic: void push_back(T&& x);};

push_back() 的参数虽然是 T&& 的形式,但这里没有类型推导,因为 push_back() 必须依赖于一个已经实例化的 vector 而存在,vector 实例化时就已经确定了 T 的类型。调用时,参数 T&& 已经确定为某个具体类型(如 int&&),是右值引用而非万能引用。相反,vector 的另一个成员函数 emplace_back 就会进行类型推导,其形式如下:

template> // still fromclass vector { // C++ Standards template void emplace_back(Args&&..、args);};

注意这里的模板参数 Args 与 vector 的模板参数 T 无关。

auto 的情形显然符合以上条件:显然存在类型推导,并且形式正确(auto&&)。

本 Item 的所有内容都是 “谎言”(高情商:是一种抽象),其底层的真相被称为 引用折叠(reference collapsing),在 Item 28 进行讨论。不过这种抽象对于正确理解源码(我看到的 T&& 只能绑定到右值还是任何对象?)很有帮助。(也有助于理解后面 Item 25 和 Item 26 的内容)

总结 如果一个模板函数的参数的形式为 T&&,且类型 T 涉及推导,或者一个对象是由 auto&& 声明,那个参数或对象就是万能引用。如果类型声明的形式不恰好是 type&&,或者没有涉及类型推导,那么 type&& 就是一个右值引用。万能引用由右值对象初始化时,就是右值引用;由左值对象初始化时,就是左值引用。

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。