Большая часть причины может заключаться в том, что подсчет ссылок больше не используется в современных реализациях STL.
Вот история (кто-то исправит меня, если я ошибаюсь): вначале реализации STL использовали подсчет ссылок и были быстрыми, но не поточнобезопасными - разработчики ожидали, что разработчики приложений вставят свои собственные механизмы блокировки на более высокие уровни , чтобы сделать их потокобезопасными, потому что, если блокировка выполнялась на 2 уровнях, это замедляло бы работу вдвое.
Однако программисты всего мира были слишком невежественны или ленивы, чтобы повсюду вставлять блокировки. Например, если рабочему потоку в многопоточной программе необходимо прочитать параметр командной строки std :: string, потребуется блокировка даже для чтения строки, в противном случае может произойти сбой. (2 потока увеличивают счетчик ссылок одновременно на разных процессорах (+1), но уменьшают его отдельно (-2), поэтому счетчик ссылок уменьшается до нуля, и память освобождается.)
Таким образом, разработчики прекратили подсчет ссылок и вместо этого каждый std :: string всегда имел собственную копию строки. Работало больше программ, но все они были медленнее.
Так что теперь даже скромное присвоение одной std :: string другой (или, что то же самое, передача std :: string в качестве параметра функции), требует около 400 инструкций машинного кода вместо 2, которые требуются для назначить символ *, замедление в 200 раз.
Я проверил величину неэффективности std :: string в одной основной программе, общее замедление которой составило около 100% по сравнению со строкой с нулевым символом в конце. Я также протестировал необработанное назначение std :: string, используя следующий код, в котором говорилось, что назначение std :: string было в 100-900 раз медленнее (У меня были проблемы с измерением скорости присваивания char *). Я также отлаживал в функции std :: string operator = () - я оказался в стеке по колено, около 7 слоев, прежде чем нажать «memcpy ()».
Я не уверен, что есть какое-то решение. Возможно, если вам нужна ваша программа, чтобы быть быстрой, использовать старый добрый C ++, и если вы больше беспокоитесь о своей производительности, вам следует использовать Java.
#define LIMIT 800000000
clock_t start;
std::string foo1 = "Hello there buddy";
std::string foo2 = "Hello there buddy, yeah you too";
std::string f;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
f = foo1;
foo1 = foo2;
foo2 = f;
}
double stl = double(clock() - start) / CLOCKS_PER_SEC;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
}
double emptyLoop = double(clock() - start) / CLOCKS_PER_SEC;
char* goo1 = "Hello there buddy";
char* goo2 = "Hello there buddy, yeah you too";
char *g;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
g = goo1;
goo1 = goo2;
goo2 = g;
}
double charLoop = double(clock() - start) / CLOCKS_PER_SEC;
TfcMessage("done", 'i', "Empty loop = %1.3f s\n"
"char* loop = %1.3f s\n"
"std::string loop = %1.3f s\n\n"
"slowdown = %f",
emptyLoop, charLoop, stl,
(stl - emptyLoop) / (charLoop - emptyLoop));