C++ 为什么传递本征表达式的临时变量会导致访问未定义的内存?

C++ 为什么传递本征表达式的临时变量会导致访问未定义的内存?,c++,eigen,C++,Eigen,在试图追踪一个bug的过程中,我想出了以下简单的程序来说明这个问题: #include <iostream> #include <Eigen/Dense> using Mat = Eigen::Matrix<double, 1, 1, Eigen::AutoAlign>; template <typename Derived> auto Modify(const Eigen::DenseBase<Derived>& valu

在试图追踪一个bug的过程中,我想出了以下简单的程序来说明这个问题:

#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;
}
在valgrind下运行生成的代码会生成一个未初始化的值,该值是由堆栈分配错误创建的

上面的代码有什么问题吗?由于原始的
mat
矩阵在矩阵求值点的作用域内,为什么我要创建
Eigen::DenseBase
表达式的临时值呢


我尝试过使用Egeng 3.2.1和Egeng 3.2.2进行编译,得到了相同的结果。

value.derived().array()
返回一个临时的
ArrayRapper
对象
2*value.derived().array()
构造一个expression对象,该对象存储对该
ArrayWrapper
的引用,但该临时
ArrayWrapper
随即被销毁。因此,您从
Modify
返回的表达式对象包含一个悬空引用。

T.C.的回答是正确的,但该行为是无意的,因为轻量级表达式应该按值嵌套,而不是按引用嵌套。
ArrayRapper
中有一个小缺点,在某些情况下,它通过引用嵌套。这在3.2和默认分支中都已修复。因此,您的示例现在运行良好。

@ooga这很有意义。你知道一种方法来确保表达式引用
派生()
类型,同时仍然公开
Eigen::Array
?@Arman看起来像:)OP声称他们使用了Eigen 3.2。我在新下载的Eigen 3.2.2副本上明确再现了这个问题。编辑-啊,我明白了,它刚刚被修复:)@T.C.是你现在在3.2.2中链接的修复程序,还是我需要下载trunk?@Arman你应该问@ggael…我假设它不在3.2.2中。对,那将在未来的3.2.3和3.3版本中。同时,您可以下载3.2分支。
first: 4
second: 3.95253e-323