我正在编写一个库,它将Eigen表达式模板存储为成员变量,以执行它需要执行的复杂计算。但是,似乎我无法存储或返回这些表达式模板,除非它们直接在MatrixXd中转换或类似。这迫使每一步都被保存到临时,并破坏了整个设计的效率。
这是一个引起麻烦的简短例子。持有者只持有一个特征矩阵,夏天需要两个持有者,并在你调用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;
}
答案 0 :(得分:1)
这是因为Holder::get
将矩阵的副本作为临时副本返回。然后,此临时值由CWiseBinaryOp
返回的Summer::get
对象存储为const引用,然后删除此临时值,最后在expr
被评估时,expr
引用已删除对象。您可以通过使Holder::get
返回对矩阵的const引用来解决此问题。