为何对const引用执行std::move时编译器不报错?
问题解析:const引用对象为何能通过std::move编译且原对象未被修改
这不是编译器bug,是对std::move和标准库容器赋值运算符重载的理解盲区,核心原因如下:
std::move本质是类型转换,不改变对象的const属性
对const std::vector<double>&类型的data调用std::move(data)时,返回的是const std::vector<double>&&(const右值引用),而非普通的右值引用std::vector<double>&&。std::move仅改变值类别,不会移除对象的const限定。std::vector赋值运算符的匹配规则
标准库std::vector的核心赋值重载有两个:- 拷贝赋值:
vector& operator=(const vector&);,接受const左值引用 - 移动赋值:
vector& operator=(vector&&);,接受非const右值引用
由于
const std::vector<double>&&无法绑定到vector&&(非const右值引用参数),编译器会匹配拷贝赋值运算符。也就是说,这段代码里的data_ = std::move(data);本质等价于data_ = data;,执行的是拷贝操作而非移动操作。- 拷贝赋值:
原对象未被修改的原因
实际执行的是拷贝赋值,源对象data本身是const限定的,不允许被修改,因此它的状态不会受到任何影响,代码自然能正常运行。
补充:正确的移动场景
只有当源对象是非const的可修改对象时,std::move才能触发真正的移动操作。比如书中推荐的传值后move写法:
void MyClass::func(std::vector<double> data) { data_ = std::move(data); }
这里的参数data是可修改的左值,std::move(data)得到非const右值引用,会匹配移动赋值运算符,从而避免不必要的拷贝。
内容的提问来源于stack exchange,提问作者DarioZ
相关产品推荐
相关产品推荐

