Я б не переймався цим. Якщо ви робите це в циклі, рядки завжди будуть виділяти пам'ять для мінімізації перерозподілу - просто використовуйте operator+=
в цьому випадку. А якщо робити це вручну, щось подібне чи довше
a + " : " + c
Тоді це створює тимчасовості - навіть якщо компілятор міг би усунути деякі копії поверненого значення. Це тому, що в послідовно викликаному operator+
він не знає, посилається параметр посилання на названий об'єкт, або тимчасовий, який повертається з додаткового operator+
виклику. Я б швидше не хвилювався з цього приводу, перш ніж не профайлювати перший. Але візьмемо приклад для показу цього. Спочатку ми вводимо круглі дужки, щоб зробити ясність чіткою. Я ставлю аргументи безпосередньо після декларації функції, яка використовується для ясності. Нижче я показую, що тоді виходить вираження:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
Тепер у цьому додатку tmp1
є те, що було повернуто першим дзвінком оператору + із показаними аргументами. Ми припускаємо, що компілятор дійсно розумний і оптимізує копію повернутого значення. Отже, ми закінчуємо однією новою рядком, що містить конкатенацію a
та " : "
. Тепер це відбувається:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
Порівняйте це з наступним:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
Він використовує ту саму функцію для тимчасової та для названої рядки! Тож компілятору належить скопіювати аргумент у новий рядок і додати до нього та повернути його з тіла operator+
. Він не може зайняти пам'ять тимчасового і додати до цього. Чим більший вираз, тим більше копій струн потрібно зробити.
Далі Visual Studio та GCC підтримуватимуть семантику переміщення c ++ 1x (доповнює семантику копії ) та посилають rvalue як експериментальне доповнення. Це дозволяє з'ясувати, чи параметр посилається на тимчасовий чи ні. Це зробить такі доповнення дивовижно швидкими, оскільки все вищезазначене опиниться в одному "додатковому конвеєрі" без копій.
Якщо це виявиться вузьким місцем, ви все одно можете зробити
std::string(a).append(" : ").append(c) ...
В append
виклики додайте аргумент *this
і потім повертає посилання на себе. Тож копіювання часописів там не робиться. Або, як варіант, operator+=
можна використовувати, але вам знадобляться потворні дужки, щоб закріпити пріоритет.