"std::move"构造函数中的Eigen对象



Eigen3文档警告不要按值传递Eigen对象,但它们只指用作函数参数的对象。

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

如果我不能在构造函数中std::moveEigen对象,这是否意味着我应该从结构中显式删除move构造函数?

例如,

#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;
};

特征对象没有什么神奇之处。固定大小的类型(如Vector3d(的行为与std::array类似。像VectorXd这样的动态大小类型的行为类似于std::vector

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

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

总结:使用pass-by-reference。移动结构对于动态大小的特征阵列是有意义的。它对固定大小的类型没有区别。

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

最新更新