Reputation: 18864
Which of the below two should be preferred and why?
struct X {
Y data_;
explicit X(Y&& data): data_(std::forward<Y>(data)) {}
};
vs
struct X {
Y data_;
explicit X(Y data): data_(std::move(data)) {}
};
Upvotes: 2
Views: 1417
Reputation: 725
It seems that the first variant only "sometimes" saves on move operation.
#include <iostream>
struct S
{
S() = default;
S(const S& other) { std::cout << "copy" << std::endl; }
S(S&& other) { std::cout << "move" << std::endl; }
};
struct Owner
{
Owner(S s) : s(std::move(s)) {}
//Owner(S&& s) : s(std::move(s)) {} // this will "sometimes" save a single move
S s;
};
S createS()
{
return S();
}
int main()
{
std::cout << "owner1:" << std::endl;
Owner owner1 = Owner(S());
std::cout << "owner2:" << std::endl;
Owner owner2 = Owner(createS());
std::cout << "owner3:" << std::endl;
S s;
Owner owner3 = Owner(std::move(s));
return 0;
}
Only use-case owner3
seems to have the two moves. However I agree that second variant is probably better until you measure that it's really a performance issue in your particular application.
Upvotes: 0
Reputation: 50044
The two variants differ in functionality. The following statements work for the second one–but not for the first one:
Y y;
X x(y);
If you are looking for the same functionality, the two variants should look as follows:
struct X
{
Y data_;
explicit X(const Y& data) : data_(data) { }
explicit X(Y&& data) : data_(std::move(data)) { }
};
struct X
{
Y data_;
explicit X(Y data) : data_(std::move(data)) { }
};
The first variant saves one move operation, whereas the second variant is less to write. So, the answer is: Use the latter as long as you have no reason to optimize the performance.
Upvotes: 6