0

我正在编写一个将 Eigen 表达式模板存储为成员变量的库,以执行它需要执行的复杂计算。但是,似乎我无法存储或返回这些表达式模板,除非它们直接在 MatrixXd 或类似中转换。这迫使每一步都被保存为暂时的,并且破坏了整个设计的效率。

这是一个导致麻烦的简短示例。Holder 只持有一个 Eigen 矩阵,Summer 需要两个持有者,并在调用 get() 时输出它们持有的两个矩阵的总和。当 sum 表达式模板被评估为矩阵时,随后的测试失败(segfault 或 std::bad_alloc)。

包含文件

#ifndef PB_SIMPLE_H
#define PB_SIMPLE_H

#include <Eigen/Dense>

template <class EigenType>
class Holder {
   public:
    typedef EigenType result_type;

   private:
    result_type in_;

   public:
    Holder(const EigenType& in) : in_(in) {}
    result_type get() const { return in_; }
};

template <class HoldLeft, class HoldRight>
class Summer {
   public:
    typedef const typename Eigen::CwiseBinaryOp<
        Eigen::internal::scalar_sum_op<double>,
        const typename HoldLeft::result_type,
        const typename HoldRight::result_type> result_type;
    // typedef Eigen::MatrixXd result_type;
   private:
    HoldLeft left_;
    HoldRight right_;

   public:
    Summer(const HoldLeft& left, const HoldRight& right)
        : left_(left), right_(right) {}

    result_type get() const { return left_.get() + right_.get(); }
};

typedef Holder<Eigen::MatrixXd> MatrixHolder;
typedef Summer<MatrixHolder, MatrixHolder> MatrixSummer;

#endif /* PB_SIMPLE_H */

简单测试

#include "PbSimple.h"

#include <Eigen/Dense>

int main(int, char * []) {
  const unsigned int szx=10,szy=3;
  Eigen::MatrixXd x(Eigen::MatrixXd::Constant(szx,szy,1));
  MatrixHolder vx(x);
  Eigen::MatrixXd y(Eigen::MatrixXd::Constant(szx,szy,2));
  MatrixHolder vy(y);
  MatrixSummer vsum(vx,vy);
  auto expr = vsum.get();
  MatrixHolder vz(expr); //force evaluation of sum into new matrix, fails here
  return 0;
}
  • 在包含文件中,如果您改用注释掉的 typedef,它可以正常工作。
  • 我怀疑这个问题是由于一个悬空的参考,但无法证明这一点。
4

1 回答 1

1

这是因为Holder::get将矩阵的副本作为临时返回。CWiseBinaryOp然后这个临时对象被返回的对象存储为一个常量引用Summer::get,然后这个临时对象被删除,最后当expr被评估时,expr引用被删除的对象。您可以通过Holder::get返回对矩阵的 const 引用来解决此问题。

于 2014-01-16T13:25:06.420 回答