简体   繁体   中英

`std::move` an Eigen object in a constructor?

The Eigen3 documentation warns against passing Eigen objects by value, but they only refer to objects being used as function arguments.

Suppose I'm using Eigen 3.4.0 and C++20. If I have a struct with an Eigen member, does this mean I can't std::move a pass-by-value in the constructor? Do I need to pass-by-reference and copy the object? Or is this handled somehow by modern move-semantics?

If I can't std::move Eigen objects in a constructor, does this mean I should explicitly delete the move-constructors from my struct?

For example,

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

There is nothing magic about Eigen objects. Fixed sized types such as Vector3d behave like std::array. Dynamic sized types like VectorXd behave like std::vector.

Pass by value for a dynamic sized type typically is a mistake because it usually invokes a copy construction which can be very expensive for large matrices. Pass by reference (const, lvalue, rvalue) is almost always the right choice [footnote 1].

Pass by value for fixed sized types can be a benefit because the first few arguments are usually passed in registers (depending on the platform). This avoids spilling values to the stack. However, this doesn't work for Eigen. I assume they declare a destructor, even if they don't need one. That turns any pass-by-value into pass-by-reference to a hidden copy. You can see this in godbolt . This seems like a missed optimization in Eigen.

In conclusion: Use pass-by-reference. Move-construction makes sense for dynamic sized eigen arrays. It makes no difference for fixed sized types.

Footnote 1: A rare exception can be cases were you would need to do a copy anyway inside the function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM