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:

  1. 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?

  2. 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?

  3. 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.

Edit
Report