C++右值引用返回值赋值给普通对象的原理及隐式转换问题
C++右值引用初始化对象问题解答
首先给出你问题中的代码片段方便对照:
template<typename T> class Stack { private: std::vector<T> elems; public: Stack () = default; Stack (T const& elem) : elems({elem}) {} }; template<typename T> Stack<T>&& dummy(Stack<T>&& a){ return std::move(a); } int main(){ Stack<int> first_a = 10; Stack<int> second_a = dummy(std::move(first_a)); ... }
为什么右值引用可以初始化Stack<int>对象
你代码中的Stack<int> second_a = dummy(...)属于对象初始化语法,不是赋值操作,核心逻辑是:
- 函数
dummy返回的Stack<T>&&类型属于C++的值类别中的「亡值」,归属于右值大类 - 右值可以直接绑定到移动构造函数的右值引用参数,用来完成新对象的构造
- 你的
Stack类没有显式禁用移动构造,编译器会自动生成默认移动构造函数,参数刚好匹配Stack<T>&&类型,因此可以直接完成初始化
底层运行逻辑
整个初始化过程的执行步骤如下:
std::move(first_a)将左值first_a显式转换为Stack<int>&&类型的亡值,作为参数传入dummy函数dummy的形参a本身是左值(即使它的类型是右值引用),内部通过std::move(a)再次转换为亡值返回- 编译器处理
second_a的初始化时,根据初始化值是右值的特征,重载决议选择默认生成的移动构造函数 - 移动构造函数内部将参数所持有的
elems容器的底层资源直接转移到second_a中,不会执行容器的深拷贝操作 - 原
first_a对象进入被移动后的有效可析构状态,内部elems变为空容器
是否存在隐式转换
整个过程不存在类型层面的隐式转换:
dummy返回的Stack<int>&&类型和移动构造函数的参数类型完全匹配,不需要做类型转换- 过程中出现的两次
std::move都属于显式的左值到右值引用的类型转换,不属于隐式转换 - 如果
Stack类没有可用的移动构造,编译器会选择拷贝构造函数,右值可以绑定到拷贝构造的const Stack<T>&参数,这个绑定是C++的标准规则,也不属于隐式转换
内容的提问来源于stack exchange,提问作者Willi
相关产品推荐
相关产品推荐

