c++ 如果取消复制省略,为什么当我按值返回时,Eigen不进行复制?

bxjv4tth  于 2022-12-20  发布在  其他
关注(0)|答案(1)|浏览(110)

我现在有一个非常简单的程序,我在我的编译器中停用了复制省略,据我所知,它甚至不应该在这里应用,因为编译器不知道我将输入什么,现在,非常奇怪的事情是,当我查看地址时,它们与我所期望的相匹配,如果函数返回的值没有发生复制,但是,当我说Eigen::MatrixXf m2 = m时,有一个副本正在发生。我不知道为什么地址匹配,因为我期望有一个副本。

#include <iostream>
#include <Eigen/Dense>

Eigen::MatrixXf no_copy(){
    Eigen::MatrixXf m =  Eigen::MatrixXf::Random(3,3);
    Eigen::MatrixXf m2 = Eigen::MatrixXf::Random(3,3);
    int c = 0;
    std::cin >> c;
    
    
    std::cout << "m" << &m(0,0) << std::endl;
    std::cout << "m2" << &m2(0,0) << std::endl;
    if (c > 0) {
        std::cout << "m " << std::endl;
        return m;
    }
    else{
        std::cout << "m2 " << std::endl;
        return m2;
    }
    
    return m;
}

int main() {

    //make a 1000 x 1000 matrix of random floats
    Eigen::MatrixXf m;
    m = no_copy();
    Eigen::MatrixXf m2 = m;

    
    std::cout << m << std::endl;
    std::cout << &m(0,0) << std::endl;
    std::cout << &m2(0,0) << std::endl;

    return 0;
}

'
我试着运行Eigen::MatrixXf m2 = std::move(m);,看看移动是否是奇怪行为的原因,但是当我尝试时,我得到了一个Assert错误。为什么Eigen不复制no_copy函数中返回的矩阵?

uoifb46i

uoifb46i1#

Eigen::MatrixXf拥有一个动态选择大小的矩阵。因此它不能直接将矩阵元素存储在自己的存储中。它必须使用动态分配,就像std::vector一样。
如果未应用NRVO,return m;将使用move构造函数来构造函数调用的临时结果对象,并且m = no_copy();还将使用move赋值运算符来从此临时结果对象赋值。如果正确实现了move操作,则它们将不执行任何额外的分配,而只是接管原始MatrixXf所做的动态分配的所有权。
您正在将地址打印到动态分配中,而动态分配不应该发生更改。
Eigen::MatrixXf m2 = m;是复制构造,而不是移动构造,所以它不能做同样的事情。它需要进行一个新的动态分配并复制这些值。地址必须不同。复制省略也是不可能的。
Eigen::MatrixXf m2 = std::move(m);会导致错误,因为尽管您已从m中移出,并且其动态分配不再归m所有,但之后您仍在尝试索引到m中。

相关问题