I'm wondering the best form for my constructors. Here is some sample code:
class Y { ... }
class X
{
public:
X(const Y& y) : m_y(y) {} // (a)
X(Y y) : m_y(y) {} // (b)
X(Y&& y) : m_y(std::forward<Y>(y)) {} // (c)
Y m_y;
}
Y f() { return ... }
int main()
{
Y y = f();
X x1(y); // (1)
X x2(f()); // (2)
}
From what I understand, this is the best the compiler can do in each situation.
(1a) y is copied into x1.m_y (1 copy)
(1b) y is copied into the argument of the constructor of X, and then copied into x1.m_y (2 copies)
(1c) y is moved into x1.m_y (1 move)
(2a) result of f() is copied into x2.m_y (1 copy)
(2b) f() is constructed into the argument of the constructor, and then copied to x2.m_y (1 copy)
(2c) f() is created on the stack, and then moved into x2.m_y (1 move)
Now a few questions:
On both counts, pass by const reference is no worse, and sometimes better than pass by value. This seems to go against the discussion on "Want Speed? Pass by Value.". For C++ (not C++0x), should I stick with pass by const reference for these constructors, or should I go pass by value? And for C++0x, should I do pass by rvalue reference over pass by value?
For (2), I'd prefer if the temporary was constructed directly into x.m_y. Even the rvalue version I think requires a move which, unless the object allocates dynamic memory, is as much work as a copy. Is there any way to code this so the compiler is permitted to avoid these copies and moves?
I've made a lot of assumptions in both what I think the compiler can do best and in my questions themselves. Please correct any of these if they are incorrect.