【问题标题】:Is returning Eigen::Ref legit?返回 Eigen::Ref 是否合法?
【发布时间】:2020-04-11 14:04:33
【问题描述】:

Eigen 的文档解释了如何将Eigen::Ref 用作函数参数。将它也用作函数返回值是不是一个好主意?

例如

class XyTracker : public XyListener {
 public:
  XyTracker() = default;
  XyTracker(XyTracker&&) = default;
  XyTracker& operator=(XyTracker&&) = default;

  const Eigen::Ref<const Eigen::ArrayXXd> Xs() const;
  const Eigen::Ref<const Eigen::ArrayXd> Ys() const;

  // XyListener
  void OnXy(const Eigen::VectorXd& x, double y) final;

 private:
  Eigen::ArrayXXd xs_;
  Eigen::ArrayXd ys_;
  Eigen::Index n_ = 0;
};

inline const Eigen::Ref<const Eigen::ArrayXXd> XyTracker::Xs() const {
  return xs_.topRows(n_);
}

inline const Eigen::Ref<const Eigen::ArrayXd> XyTracker::Ys() const {
  return ys_.head(n_);
}

【问题讨论】:

  • 至少,您必须注意确保生命周期。
  • 使用 Eigen::Ref 作为返回类型没有错

标签: c++ eigen eigen3


【解决方案1】:

正如 cmets 中已经指出的那样,返回 Ref 对象没有任何问题,只要您确保您引用的对象在您使用引用时仍然有效。

简化示例:

struct A {
    ArrayXXd xs;
    Ref<const ArrayXXd> Xs() const {
        return xs.topRows(5);  // works (when used properly)
    }
    Ref<const ArrayXXd> NotWorking() const {
        ArrayXXd foo = 2*xs;
        return foo.topRows(5); // compiles, but will give U.B.
};


// usage:
A a;
a.xs.setRandom(10,10);

Ref<const ArrayXXd> r1 = a.Xs();
// fine to use r1 here
a.xs.setRandom(20,20);
// from here on r1 will point to non-existing memory
// i.e., using r1 will be U.B.

U.B. (未定义的行为)示例本质上都是 use-after-free,不幸的是编译器几乎没有检测到它们,因此在使用 Eigen::Ref 时需要小心一些。 UB 可能意味着您的单元测试可以正常工作,尽管您的代码很糟糕,但是在生产中突然出现段错误...

【讨论】:

    猜你喜欢
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2019-12-23
    • 2014-02-03
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    相关资源
    最近更新 更多