Я бы не беспокоился об этом. Если вы делаете это в цикле, строки всегда будут предварительно выделять память, чтобы минимизировать перераспределение - просто используйте 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+=
можно использовать, но вам понадобятся уродливые круглые скобки для исправления приоритета.