Ответ 1
Это выполнит 1 конструкцию копии и 3 перемещения.
- Сделайте копию
a
для привязки кlhs
. - Переместить конструкцию
lhs
из первого+
. - Возврат первого
+
будет привязан к параметруlhs
по значению второго+
с разрешением. - Возврат второго
lhs
приведет к второй конструкции перемещения. - Возврат третьего
lhs
приведет к третьей конструкции перемещения. - Временное, возвращаемое с третьего
+
, будет построено вsum
.
Для каждой из описанных выше перемещающих конструкций существует другая конструкция перемещения, которая необязательно устранена. Таким образом, у вас есть только 1 копия и 6 ходов. Но на практике, если вы не -fno-elide-constructors
, у вас будет 1 копия и 3 хода.
Если вы не ссылаетесь на a
после этого выражения, вы можете продолжить оптимизацию с помощью:
X sum = std::move(a) + b + c + d;
что приводит к 0 копиям и 4 ходам (7 движений с -fno-elide-constructors
).
Вышеуказанные результаты были подтверждены с помощью X
, который имеет инструменты копирования и перемещения конструкторов.
Обновление
Если вас интересуют различные способы оптимизации этого, вы можете начать с перегрузки lhs на X const&
и X&&
:
friend X operator+(X&& lhs, X const& rhs) {
lhs += rhs;
return std::move(lhs);
}
friend X operator+(X const& lhs, X const& rhs) {
auto temp = lhs;
temp += rhs;
return temp;
}
Это уменьшает до 1 копии и 2 хода. Если вы хотите ограничить доступ своих клиентов к возврату вашего +
по ссылке, вы можете вернуть X&&
из одной из перегрузок, как это:
friend X&& operator+(X&& lhs, X const& rhs) {
lhs += rhs;
return std::move(lhs);
}
friend X operator+(X const& lhs, X const& rhs) {
auto temp = lhs;
temp += rhs;
return temp;
}
Доведение до 1 копии и 1 переход. Обратите внимание, что в этом последнем дизайне, если вы это делаете, клиент:
X&& x = a + b + c;
то X
- это болтающаяся ссылка (поэтому std::string
этого не делает).