Home > Software engineering >  Is it worth moving a small `std::vector<POD>`?
Is it worth moving a small `std::vector<POD>`?

Time:12-09

If you have a small (say, < 10 elements) std::vector<T> of PODs, is there much benefit to using std::move()?

In a codebase I'm looking at, I see a lot of code like this:

std::vector<double> temp{1.0, 2.0, 3.0, 6.0};

class some_class {
 public:
   some_class(const std::vector<double>& _vals) : vals{_vals} {}

 private:
   std::vector<double> vals; 
}

some_class{temp};

// temp is never used again afterwards

I'm wondering if there's much benefit to changing it to this?

std::vector<double> temp{1.0, 2.0, 3.0, 6.0};

class some_class {
 public:
   some_class(std::vector<double>&& _vals) : vals{std::move(_vals)} {}

 private:
   std::vector<double> vals; 
}

some_class{std::move(temp)};

// temp is never used again afterwards

CodePudding user response:

Using move semantics will likely avoid an extra allocation, which may or may not be considered significant in your domain. I doubt that copying of the elements itself is significant.

const std::vector<double>& can't be replaced by std::vector<double>&& because then the class becomes unusable with lvalue arguments.

It is possible to defined both overloads, but usually taking by-value and then moving into the member is sufficient. It may cost one extra move operation compared to two reference overloads, which is insignificant for std::vector:

some_class(std::vector<double> _vals) : vals{std::move(_vals)} {}

Then the user of the class can move into the constructor if that makes sense in the program logic at the call site:

some_class{std::move(temp)};

(Although the above line creates and immediately destroys a temporary object, which probably doesn't make much sense to begin with.)

CodePudding user response:

You can change your variable declarations from

std::vector<double> temp{1.0, 2.0, 3.0, 6.0};

to any of these (whichever is better for you):

static const auto temp = {1.0, 2.0, 3.0, 6.0};
static const std::initializer_list<double> temp = {1.0, 2.0, 3.0, 6.0};
constexpr auto temp = {1.0, 2.0, 3.0, 6.0};
constexpr std::initializer_list<double> temp = {1.0, 2.0, 3.0, 6.0};

In this case when you will use this variable in expression

some_class{temp};

it will compile to basically same code as if you did

some_class{{1.0, 2.0, 3.0, 6.0}};
  • Related