В стандарте C ++ std:string
следует политике экспоненциального роста, поэтому я полагаю, capacity()
строки во время конкатенации всегда будет увеличиваться при необходимости. Тем не менее, когда я тестирую test.cpp
Я обнаружил, что в цикле, только каждые два раза будет ли capacity()
быть возвращенным к length()
во время назначения.
Почему это поведение не зависит от длины строки, а зависит от того, как часто я меняю строку? Это какая-то оптимизация?
Следующие коды проверены с g++ -std=c++11
,
test.cpp:
#include <iostream>
int main(int argc, char **argv) {
std::string s = "";
for (int i = 1; i <= 1000; i++) {
//s += "*";
s = s + "*";
std::cout << s.length() << " " << s.capacity() << std::endl;
}
return 0;
}
И вывод будет таким:
1 1
2 2
3 4
4 4
5 8
6 6 // why is capacity shrunk?
7 12
8 8 // and again?
9 16
10 10 // and again?
11 20
12 12 // and again?
13 24
14 14 // and again?
15 28
16 16 // and again?
17 32
...
996 996
997 1992
998 998 // and again?
999 1996
1000 1000 // and again?
Когда вы делаете это:
s = s + "*";
Вы делаете две разные вещи: создаете новую временную строку, состоящую из "*"
соединены в конец содержимого s
и затем скопировать, присвоив эту новую строку s
,
Это не +
это сокращается, это =
, При назначении копирования из одной строки в другую нет смысла копировать емкость, а только фактически используемые байты.
Ваш закомментированный код делает это:
s += "*";
… делает только одну вещь, добавляя "*"
на конец s
, Так что «оптимизации» некуда (если это произойдет, это будет pessimization, победить всю цель экспоненциального роста).
Это на самом деле не соответствует стандарту C ++, что происходит с capacity()
когда строки перемещаются, присваиваются и т. д. Это может быть дефектом. Единственными ограничениями являются те, которые выводятся из временной сложности, указанной для операции.
Посмотреть здесь для аналогичного обсуждения о векторах.