为何我的Move构造函数未真正完成对象移动?
问题分析与解决
你代码里的移动操作没生效,核心问题出在Foo的构造函数初始化逻辑里:
- 虽然你用
std::move(vals)把vals转成右值传给了Foo的构造函数,但构造函数里的参数x是右值引用变量,只要有名字的变量都是左值,所以初始化x_(x)时调用的是vector的拷贝构造函数,而非移动构造函数。
修正方法
把Foo构造函数的初始化列表改成x_(std::move(x)),显式把左值化的右值引用参数转回右值,触发移动构造:
#include <vector> #include <iostream> class Foo { public: explicit Foo(std::vector<int>&& x) : x_(std::move(x)) {} // 这里添加std::move触发移动构造 void myaddr() { std::cout << "addr (foo ) = " << &x_ << std::endl; std::cout << "foo.x_ 内部数据地址 = " << x_.data() << std::endl; } private: std::vector<int> x_; }; int main() { std::vector<int> vals = {1, 2}; std::cout << "addr (main) = " << &vals << std::endl; std::cout << "vals 内部数据地址 = " << vals.data() << std::endl; Foo foo(std::move(vals)); foo.myaddr(); // 移动后vals处于有效但未定义状态,打印其内部地址大概率为空或旧值 std::cout << "移动后vals内部数据地址 = " << vals.data() << std::endl; }
关键说明
你之前误以为移动后&vals和&foo.x_地址会相同,这是误解:
vals是main栈帧里的局部变量,foo.x_是Foo对象的成员变量,它们的栈存储位置本来就不同,移动操作不会改变对象本身的存储地址。- 移动的本质是转移vector内部管理的堆内存资源,也就是
data()返回的地址。修正后你会看到:移动前vals.data()和foo.x_.data是同一个,移动后foo的内部数据地址不变,而vals的内部数据地址会变为空(或其他无效值),这才是移动生效的标志。
内容的提问来源于stack exchange,提问作者fatdragon
相关产品推荐
相关产品推荐

