C++中如何用右值引用初始化std::variant<Type1,Type2>&&变量?
结论先行
你使用std::variant<Type1, Type2>&& myVariant(std::move(t));的初始化方式在大部分场景下是合法可用的,但存在一定的适用限制,更推荐使用完美转发的写法。
原理说明
- 首先你需要明确:C++中右值引用类型的变量必须在声明时完成初始化,你最开始写的
std::variant<Type1, Type2>&& myVariant;未初始化本身就属于编译错误。 - 为什么
std::variant<Type1, Type2>&& myVariant = t;无法运行:
你的模板参数Type&&属于转发引用,当传入参数是左值时,t本身是左值类型,无法直接构造临时variant对象并绑定到右值引用上,因此编译失败。 - 为什么
std::move(t)的写法可以运行:std::move(t)会无条件将t转为右值类型,此时可以匹配std::variant的移动构造函数生成临时对象,右值引用myVariant会绑定到这个临时对象,同时临时对象的生命周期会被延长到和myVariant一致,符合C++标准要求。
存在的限制&优化建议
- 如果你后续还需要使用原参数
t,std::move(t)的写法会导致t被移动后处于合法但未定义的状态,继续使用会触发未定义行为。 - 更稳妥的写法是使用完美转发替代无条件移动,适配左值、右值传入的场景:
这种写法语义更准确:传入左值时调用std::variant<Type1, Type2>&& myVariant(std::forward<Type>(t));variant的拷贝构造,传入右值时调用移动构造,不会误移动还需要使用的左值参数。 - 如果你没有特殊需求必须使用右值引用,直接声明普通
variant对象更直观,也没有生命周期隐患:std::variant<Type1, Type2> myVariant(std::forward<Type>(t));
内容的提问来源于stack exchange,提问作者PrueWho
相关产品推荐
相关产品推荐

