Я был довольно удивлен, увидев, что Джонатан Вакели, оптимизированный в libstdc++, оптимизирован: https://gcc.gnu.org/ml/libstdc++/2018-05/txtc2I3IxLCfn.txt и попытался расследовать это.
Учитывая пару реализаций concat-функции для любого нетривиального класса, удивительно, что только первый является оптимальным (один экземпляр c-tor и один operator+ = вызов). Другие требуют дополнительного копирования/перемещения вызова c-tor - вы можете проверить его на godbolt.org.
Это почему? Я бы предположил, что вся эта реализация будет генерировать тот же код с -O2.
Указывает ли спецификация языка такое поведение (если да, почему?) Или это проблема QoI?
Это согласованное поведение между GCC и Clang для всех версий и языковых версий.
void extern_copy();
void extern_move();
void extern_plus_assign();
struct myclass
{
myclass(const myclass&)
{
extern_copy();
}
myclass(myclass&&)
{
extern_move();
}
myclass& operator+=(const myclass&)
{
extern_plus_assign();
return *this;
}
};
myclass concat(const myclass& lhs, const myclass& rhs)
{
myclass copy(lhs);
copy += rhs;
return copy;
}
myclass concat2(const myclass& lhs, const myclass& rhs)
{
myclass copy(lhs);
return copy += rhs;
}
myclass concat3(const myclass& lhs, const myclass& rhs)
{
return myclass(lhs) += rhs;
}
static myclass concat4impl(myclass lhs, const myclass& rhs)
{
return lhs += rhs;
}
myclass concat4(const myclass& lhs, const myclass& rhs)
{
return concat4impl(lhs, rhs);
}
static myclass concat5impl(myclass lhs, const myclass& rhs)
{
lhs += rhs;
return lhs;
}
myclass concat5(const myclass& lhs, const myclass& rhs)
{
return concat5impl(lhs, rhs);
}
Обновление: код изменен, чтобы исключить проблему с последующей реализацией operator+ =:
myclass& myclass::operator+=(myclass const& v) {
static myclass weird;
return weird;
}