我现在有一个非常简单的程序,我在我的编译器中停用了复制省略,据我所知,它甚至不应该在这里应用,因为编译器不知道我将输入什么,现在,非常奇怪的事情是,当我查看地址时,它们与我所期望的相匹配,如果函数返回的值没有发生复制,但是,当我说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
函数中返回的矩阵?
1条答案
按热度按时间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
中。