Почему определенные типы конкатенации строк значительно быстрее других?

Рассмотрим следующие четыре случая:

#include <string>
int main()
{
    std::string s("Hi I'm Da");

 1. s += "n";
 2. s += 'n';
 3. s = s + "n";
 4. s = s + 'n';

    return 0;
}

Запуск этого тестового набора с вызовом:

g++ -std=c++11 -O3 -DVER=case -Wall -pedantic -pthread test.cpp -o test

с использованием g++ версии 4.8.3 20140624, я получаю следующие результаты:

2.16172ms
0.48296ms
510.202ms
510.455ms

Теперь я могу понять, что += быстрее, потому что вы не делаете копию с + перед назначением, но почему случаи 1 и 2 показывают значительную разницу по сравнению с примерами 3 и 4? Также, как использование двойных кавычек или одиночных кавычек влияет на скорость конкатенации?

Ответ 1

s += "n";

Это работает на строке на месте. Существует вероятность того, что перераспределение памяти не потребуется. Но строковые литералы представляют собой последовательности символов с нулевым символом, поэтому код должен найти значение 0 в памяти после "n".

s += 'n';

Это похоже на первое, но вместо строкового литерала используется символьный литерал. Нет необходимости искать 0, поэтому он может быть быстрее.

s = s + "n";

Найти 0 есть, но более того - гораздо больше - нужно создать новый временный строковый объект, и, скорее всего, это означает распределение памяти, которое на порядок или более дорого.

s = s + 'n';

Может быть быстрее предыдущего, но разница, вызванная поиском 0, скорее всего, незначительна по сравнению с временным созданием и распределением объектов в куче.

Обратите внимание на все "возможно" и "может быть". То, что я описал, может случиться в популярных компиляторах, но различные оптимизации могут полностью изменить изображение.