Требуется ли std::string кучная память?
У меня есть простой вопрос. Я хочу знать, выделяет ли std::string
память каждый раз в С++.
В моем коде кажется, что конструктор будет использовать больше памяти для построения tst_first_string
, чем для tst_second_string
:
char* first_string = new char[5];
strcpy(first_string, "test");
std::string tst_first_string(first_string);
std::string tst_second_string("test");
Ответы
Ответ 1
Оба tst_first_string
и tst_second_string
будут построены с использованием конструктора до const char*
. Поскольку число символов до nul-terminator одинаково в обоих случаях, вы можете себе представить, что конструкция будет точно идентичной. Тем не менее, стандарт С++ намеренно неопределенен относительно того, что должно произойти в отношении управления памятью, чтобы вы не знали с абсолютной уверенностью.
Обратите также внимание на то, что многие реализации std::string
используют метод оптимизации коротких строк для небольших строк, что заставляет весь объект записываться в память с автоматическим временем хранения. В вашем случае динамическая память может вообще не использоваться.
То, что мы знаем наверняка, это то, что начиная с С++ 11 копирование на семантику записи для std::string
больше не разрешено, поэтому будут созданы две различные строки.
Ответ 2
Это зависит от реализации и длины строки.
Большинство основных реализаций имеют короткую оптимизацию строк (SSO), где строка хранится в самом объекте строки.
Ответ 3
Это реализация, но в качестве примера реализация std::basic_string
в Visual С++ 2015 Update 3 будет использовать внутренний массив, если длина строки меньше 16 байт. Здесь сильно отредактированная часть _String_val
из <xstring>
:
template<class _Val_types>
class _String_val
{
public:
typedef typename _Val_types::value_type value_type;
enum
{ // length of internal buffer, [1, 16]
_BUF_SIZE = 16 / sizeof (value_type) < 1 ? 1
: 16 / sizeof (value_type)
};
value_type *_Myptr()
{ // determine current pointer to buffer for mutable string
return (this->_BUF_SIZE <= _Myres
? _Bx._Ptr
: _Bx._Buf);
}
union _Bxty
{ // storage for small buffer or pointer to larger one
value_type _Buf[_BUF_SIZE];
pointer _Ptr;
} _Bx;
};
Если вы посмотрите _Myptr()
, вы заметите, что _Buf
используется, когда длина меньше _BUF_SIZE
и _Ptr
используется иначе.
Излишне говорить, что вы не должны полагаться на то, что это верно для всего, кроме этой конкретной реализации стандартной библиотеки. Это внутренняя деталь, которая может измениться в любое время.
Ответ 4
Строковые литералы доступны только для чтения. Поэтому вероятная оптимизация заключается в том, что когда std::string указывает на литерал, он состоит только из char * плюс флаг, чтобы сказать, что это то, что он представляет. Когда вы пишете, конечно, ему придется выделять память.