Символы в basic_string хранятся в буфере, который является единым фрагментом памяти статического размера. Этот буфер, используемый строкой, изначально имеет некий размер, и по мере добавления в строку символов он заполняется до тех пор, пока не будет достигнут предел его емкости. Когда это происходит, буфер увеличивается. В частности, выделяется новый буфер большего размера, символы копируются из старого буфера в новый, и старый буфер удаляется.

Определить размер буфера (не число символов, в нем содержащихся, а его максимальный размер) можно с помощью метода capacity. Если требуется вручную установить емкость и избежать ненужных копирований буфера, используйте метод reserve и передайте ему числовой аргумент, указывающий требуемый размер буфера. Также имеется максимально возможный размер буфера, получить который можно с помощью вызова max_size. Это все можно использовать, чтобы посмотреть на расходование памяти в данной реализации стандартной библиотеки. Посмотрите на пример 4.9, показывающий, как это сделать.

Пример 4.9. Длина строки и ее емкость

#include

#include

using namespace std;

int main() {

 string s = "";

 string sr = "";

 sr.reserve(9000);

 cout << "s.length = " << s.length( ) << '\n';

 cout << "s.capacity = " << s.capacity( ) << '\n';

 cout << "s.max.size = " << s.max_size() << '\n';

 cout << "sr.length = " << sr.length() << '\n';

 cout << "sr.capacity = " << sr.capacity() << '\n';

 cout << "sr.max_size = " << sr.max_size() << '\n';

 for (int i = 0; i < 10000; ++i) {

  if (s.length() == s.capacity()) {

   cout << "s достигла емкости " << s.length() << увеличение... \n";

  }

  if (sr.length() == sr.capacity()) {

   cout << "sr достигла емкости " << sr.length() << ", увеличение...\n";

  }

  s += 'x';

  sr += 'x';

 }

}

При использовании Visual C++ 7.1 вывод выглядит так.

s.length = 0

s.capacity = 15

s.max_size = 4294967294

sr.length = 0

sr.capacity = 9007

sr.max_size = 4294967294

s достигла емкости 15, увеличение...

s достигла емкости 31, увеличение...

s достигла емкости 47, увеличение...

s достигла емкости 70, увеличение...

s достигла емкости 105, увеличение...

s достигла емкости 157, увеличение...

s достигла емкости 235, увеличение...

s достигла емкости 352, увеличение...

s достигла емкости 528, увеличение...

s достигла емкости 792, увеличение...

s достигла емкости 1188, увеличение...

s достигла емкости 1782, увеличение...

s достигла емкости 2673, увеличение...

s достигла емкости 4009, увеличение...

s достигла емкости 6013, увеличение...

sr достигла емкости 9007, увеличение...

s достигла емкости 9019, увеличение...

Здесь происходит то, что буфер строки заполняется по мере добавления в него символов. Если буфер оказывается полон (т.е. длина = емкость), выделяется новый буфер, и символы оригинальной строки и новый добавляемый символ (или символы) копируются в этот новый буфер, s начинает заполняться с емкости 15 (зависит от компилятора), а затем увеличивается каждый раз примерно на 50%.

Если ожидается значительное увеличение строки или имеется большое количество строк, которые будут увеличиваться хотя бы немного, для минимизации числа перераспределений буфера используйте reserve. Также следует провести эксперименты с имеющейся реализацией стандартной библиотеки и посмотреть, как она выполняет увеличение строк.

Кстати, когда потребуется узнать, пуста ли строка, не сравнивайте ее размер с нулем, а просто вызовите метод empty. Это метод, который возвращает истину, если длина строки равна нулю.

<p>4.5. Обращение строк</p>Проблема

Требуется обратить (реверсировать) строку.

Решение
Перейти на страницу:

Похожие книги