为何C++中可两次从右值赋值?实测与《C++ Primer》描述存疑
关于C++中std::move后被移动对象值的困惑
我在阅读《C++ Primer》第13章时看到以下内容:
必须认识到,move调用承诺我们除了赋值或销毁外,不会再使用[右值]。move调用后,我们无法对被移动对象的值做任何假设。
我们可以销毁被移动对象,也可以为其赋新值,但不能使用被移动对象的值。
为了验证“无法重复使用被移动对象的值”,我编写了如下测试代码:
#include <iostream> int main(int argc, const char * argv[]) { int&& rvalue = 42; int lvalue1 = std::move(rvalue); std::cout << "lvalue1 = " << lvalue1 << std::endl; int lvalue2 = std::move(rvalue); std::cout << "lvalue2 = " << lvalue2 << std::endl; return 0; }
但基于C++11标准编译运行后,输出显示可多次使用被移动对象的值,这与书中描述矛盾,我对此感到困惑:
lvalue1 = 42 lvalue2 = 42
问题解析
- 内置类型(如
int)的移动操作本质就是拷贝。这类简单类型没有需要转移的复杂资源,std::move仅将右值引用转换为亡值(xvalue),但实际赋值时仍会拷贝值,所以多次读取原对象不会出问题。但这是编译器的实现行为,不是C++标准强制保证的。 - 《C++ Primer》的描述针对的是拥有复杂资源的类类型(如
std::string、std::vector)。这类对象被移动后,原对象会处于“有效但未定义”的状态——比如vector被移动后可能变为空,string被移动后可能变为空串,但标准没有规定具体状态,因此绝对不能依赖原对象的值,否则会导致未定义行为。
内容的提问来源于stack exchange,提问作者Autechre
相关产品推荐
相关产品推荐

