【问题标题】:`std::move` an Eigen object in a constructor?`std::move` 构造函数中的 Eigen 对象?
【发布时间】:2022-12-23 00:41:40
【问题描述】:

The Eigen3 documentation warns against passing Eigen objects by value, 但它们仅指用作函数参数的对象。

假设我使用的是 Eigen 3.4.0 和 C++20。如果我有一个带有 Eigen 成员的 struct,这是否意味着我不能 std::move 在构造函数中按值传递?我是否需要按引用传递并复制对象?或者这是由现代移动语义以某种方式处理的?

如果我不能在构造函数中使用 std::move Eigen 对象,这是否意味着我应该明确地从我的结构中删除移动构造函数?

例如,

#include <utility>
#include <Eigen/Core>

struct Node {
  Eigen::Vector3d position;
  double temperature;

  // is this constructor safe to use?
  Node(Eigen::Vector3d position_, const double temperature_)
    : position(std::move(position_)), temperature(temperature_) {}

  // or must it be this?
  Node(const Eigen::Vector3d& position_, const double temperature_)
    : position(position_), temperature(temperature_) {}

  // also, should move-constructors be explicitly deleted?
  Node(Node&&) = delete;
  Node& operator=(Node&&) = delete;
};

【问题讨论】:

  • 您是否认为构造函数参数不是函数参数(它是),或者它没有被复制(它是)?
  • 从第一个构造函数中没有任何好处,你为什么会喜欢它?通过引用传递并让 Eigen 复制构造函数执行它的操作。你不需要对移动语义做任何事情,Vector3d 有固定的分配,std::move 没有任何好处——它对动态分配的对象很有用

标签: c++ eigen eigen3


【解决方案1】:

Eigen 对象没有什么神奇之处。固定大小的类型,例如 Vector3d 的行为类似于 std::arrayVectorXd 等动态大小类型的行为类似于 std::vector

动态大小类型的按值传递通常是错误的,因为它通常会调用复制构造,这对于大型矩阵来说可能非常昂贵。传递引用(constlvaluervalue)几乎总是正确的选择 [脚注 1]。

固定大小类型的按值传递可能是一个好处,因为前几个参数通常在寄存器中传递(取决于平台)。这避免了将值溢出到堆栈。但是,这对 Eigen 不起作用。我假设他们声明了一个析构函数,即使他们不需要一个。这会将任何按值传递转换为对隐藏副本的按引用传递。你可以在godbolt看到这个。这似乎是 Eigen 中遗漏的优化。

总之:使用传递引用。移动构造对于动态大小的特征数组是有意义的。它对固定大小的类型没有影响。

脚注 1:一个罕见的例外情况是您无论如何都需要在函数内部进行复制。

【讨论】:

    猜你喜欢
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    • 2013-01-24
    • 2013-01-22
    相关资源
    最近更新 更多