Reputation: 5894
Below in the question is a simplified version of code for SO. The original code:
const
The simplified code for SO doesn't have the original structure, I just made up data with loops. However the detail which is still important is that the new structure's constructor will be passed std::vector
. Those are populated in the loops and moved to the new structure
It occurred to me that the std::vector
will not be needed after the new structure is made so std::move
would be appropriate. I have labeled the usages as "Move 1", "Move 2", "Move 3", and "Move 4" in the code below:
#include <iostream>
#include <vector>
struct A {
const int m_a;
A() = delete;
A(const int a_a) : m_a(a_a) {}
void display() const { std::cout << " " << m_a << "\n"; }
};
struct B {
const std::vector<A> m_as;
const int m_b;
B() = delete;
B(
std::vector<A>&& a_as,
const int a_b
) :
m_as(std::move(a_as)), // Move 1
m_b(a_b)
{}
void display() const {
std::cout << " " << m_b << ":\n";
for (const A& a : m_as)
a.display();
}
};
struct C {
const std::vector<B> m_bs1;
const std::vector<B> m_bs2;
C() = delete;
C(
std::vector<B>&& a_bs1,
std::vector<B>&& a_bs2
) :
m_bs1(std::move(a_bs1)), // Move 2
m_bs2(std::move(a_bs2)) // Move 2
{}
void display() const {
std::cout << "0:\n";
for (const B& b : m_bs1)
b.display();
std::cout << "1:\n";
for (const B& b : m_bs2)
b.display();
}
};
int main() {
// Manually making up data, actual usage will take data from a different
// kind of structure and populate vectors
std::vector<B> bs1, bs2;
for (int i = 0; i < 3; ++i) {
std::vector<A> as;
for (int j = 0; j < 2; ++j)
as.emplace_back(j);
bs1.emplace_back(std::move(as), i); // Move 3
}
for (int i = 0; i < 3; ++i) {
std::vector<A> as;
for (int j = 0; j < 2; ++j)
as.emplace_back(j);
bs2.emplace_back(std::move(as), i); // Move 3
}
C c(std::move(bs1), std::move(bs2)); // Move 4
c.display();
return 0;
}
Some assumptions:
std::forward
is not a good replacement for any of the std::move
usages because there are no templatesThe question:
Are all of the std::move
usages meaningful or are any of them unnecessary?
Upvotes: 3
Views: 278
Reputation: 36379
You can see most of the std::move
s are required by removing them, your code wont compile. The only exceptions are Move 1
and Move 2
, the code will still compile without them but only because the std::vector
copy constructor is invoked instead.
If you want to move from an object you almost always need to use std::move
, the only exceptions are when moving from a temporary and when returning an object.
Upvotes: 4