You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::move转移所有权后仍可访问原矩阵?求解析行为

关于Eigen矩阵使用移动语义后访问原对象的行为疑问

先看你写的代码:

类定义代码

class MyC {
public:
    Eigen::MatrixXd f_bar_mat;
    
    MyC(Eigen::MatrixXd f_bar_mat) : f_bar_mat(std::move(f_bar_mat)) {}
};

main函数代码

Eigen::MatrixXd f_bar_mat = Eigen::MatrixXd::Random(10000,200);
MyC MyInst(f_bar_mat);
MyC MyNewInst(MyInst.f_bar_mat); //再次转移
std::cout << "Access some element of the original matrix: " << f_bar_mat(3,2) << std::endl;

核心问题解答

  • 你的代码里根本没触发对原f_bar_mat的移动
    你构造MyInst时传的是左值f_bar_mat,而构造函数的参数是值传递(Eigen::MatrixXd f_bar_mat),这时候编译器会先对原f_bar_mat做深拷贝,把拷贝结果传给构造函数的参数,之后你对参数做std::move只是把这个拷贝出来的临时对象移动到类成员里——原main函数中的f_bar_mat自始至终都没被移动过,状态完全正常,所以访问它当然不会出问题。
    同理,构造MyNewInst时传的MyInst.f_bar_mat也是左值,同样会先深拷贝,再移动参数到成员,原MyInst.f_bar_mat也没被移动。

  • std::move的本质不是执行移动,只是类型转换
    std::move本身不做任何内存转移或拷贝操作,它只是把一个左值强制转换成右值引用,告诉编译器:这个对象可以被移动了。真正的移动操作是由对象的移动构造函数/移动赋值运算符完成的,只有当传递的是右值(或者被std::move转成右值的左值)时,才会触发移动语义。

  • 如果真的移动了原对象,访问它属于未定义行为
    如果你改成MyC MyInst(std::move(f_bar_mat));,这时候就会触发对原f_bar_mat的移动构造:Eigen的矩阵会把原矩阵的内存所有权转移到新对象,原矩阵会变成一个有效但未指定状态的对象(可能是空矩阵,也可能还保留旧内存,但标准没规定)。这时候访问原f_bar_mat的元素属于未定义行为——可能正常输出,可能崩溃,可能输出垃圾值,完全看编译器和运行环境,不是必然会触发段错误。

内容的提问来源于stack exchange,提问作者KeynesCoeFen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:05:53