Мне интересно, какая форма для моих конструкторов. Вот пример кода:
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)
}
Из того, что я понимаю, это лучшее, что может сделать компилятор в каждой ситуации.
(1a) y копируется в x1.m_y (1 экземпляр)
(1b) y копируется в аргумент конструктора X, а затем копируется в x1.m_y (2 экземпляра)
(1c) y перемещается в x1.m_y (1 ход)
(2a) результат f() копируется в x2.m_y (1 экземпляр)
(2b) f() строится в аргументе конструктора, а затем копируется в x2.m_y (1 экземпляр)
(2c) f() создается в стеке, а затем перемещается в x2.m_y (1 ход)
Теперь несколько вопросов:
-
По обоим подсчетам, pass by const ссылается не хуже, а иногда лучше, чем по значению. Это, похоже, противоречит обсуждению "Want Speed? Pass by Value" .. Для С++ (а не С++ 0x) следует ли придерживаться ссылки pass by const для этих конструкторов, или мне нужно перейти по значению? И для С++ 0x, должен ли я передавать значение rvalue через pass по значению?
-
Для (2), я бы предпочел бы, чтобы временное было построено непосредственно в x.m_y. Даже версия rvalue, на мой взгляд, требует перемещения, которое, если объект не распределяет динамическую память, не работает как копия. Есть ли способ кодировать это, чтобы компилятору было разрешено избегать этих копий и перемещаться?
-
Я сделал много предположений в том, что, по моему мнению, компилятор может сделать лучше всего и в моих вопросах. Пожалуйста, исправьте их, если они неверны.