在尝试追踪错误时,我已经能够提出以下简单程序来说明问题:
#include <iostream>
#include <Eigen/Dense>
using Mat = Eigen::Matrix<double, 1, 1, Eigen::AutoAlign>;
template <typename Derived>
auto Modify(const Eigen::DenseBase<Derived>& value)
-> decltype(2*value.derived().array())
{
return 2*value.derived().array();
}
Mat Make()
{
Mat mat;
mat << 2;
return mat;
}
int main()
{
auto mat = Make();
std::cout
<< "first: " << Modify(mat) << std::endl
<< "second: " << Modify(Modify(mat));
return 0;
}
该程序的输出是:
first: 4 second: 3.95253e-323
在valgrind下运行生成的代码会产生Uninitialised value was created by a stack allocation
错误。
上述代码有什么问题吗?由于原始mat
矩阵在评估矩阵的范围内,为什么我正在创建Eigen::DenseBase
表达式的临时值?
我尝试使用Eigen 3.2.1以及Eigen 3.2.2进行编译并得到相同的结果。
答案 0 :(得分:3)
value.derived().array()
返回一个临时的ArrayWrapper
对象。 2 * value.derived().array()
构造一个表达式对象,该对象存储对该ArrayWrapper
的引用,但之后会立即销毁该临时ArrayWrapper
。因此,从Modify
返回的表达式对象包含悬空引用。
答案 1 :(得分:3)
T.C.的答案是正确的但是这种行为是无意的,因为轻量级表达式应该被值嵌套,而不是通过引用嵌套。在ArrayWrapper
中存在一些缺点,在某些情况下它会被引用嵌套。现在,3.2和默认分支都已修复此问题。所以你的例子现在工作正常。