Как мне выделить std::string в стеке, используя реализацию glibc string?

StackOverflow https://stackoverflow.com/questions/783944

Вопрос

int main(void)
{
   std::string foo("foo");
}

Насколько я понимаю, приведенный выше код использует распределитель по умолчанию для вызова new .Таким образом, даже несмотря на то, что std::string foo выделен в стеке, внутренний буфер внутри foo выделен в куче.

Как я могу создать строку, которая полностью размещается в стеке?

Это было полезно?

Решение

Недавно я сам хотел сделать именно это и обнаружил, что следующий код освещает:

stack_container от Chronium.h

Это определяет новый std::allocator который может обеспечить распределение на основе стека для первоначального выделения хранилища для контейнеров STL.В итоге я нашел другой способ решить свою конкретную проблему, поэтому на самом деле я сам не использовал код, но, возможно, он будет полезен вам.Обязательно прочитайте комментарии в коде, касающиеся использования и предостережений.

Для тех, кто сомневался в полезности и разумности этого, рассмотрим:

  • Часто вы априори знаете, что ваша строка имеет разумный максимальный размер.Например, если строка будет хранить 32-разрядное целое число в десятичном формате, вы знаете, что для этого вам не нужно более 11 символов.В этом случае нет необходимости в строке, которая может динамически увеличиваться до неограниченного размера.
  • Выделение из стека во многих случаях происходит быстрее, чем выделение из кучи.
  • Если строка создается и уничтожается часто (предположим, что это локальная переменная в часто используемой служебной функции), выделение из стека вместо кучи позволит избежать оттока в распределителе кучи, вызывающего фрагментацию.Для приложений, которые используют много памяти, это может изменить правила игры.

Некоторые люди прокомментировали, что строка, использующая выделение на основе стека, не будет std::string как будто это каким-то образом уменьшает его полезность.Правда, вы не можете использовать эти два понятия взаимозаменяемо, поэтому вы не сможете передать свой stackstring к функциям, ожидающим std::string.Но (если вы сделаете это правильно), вы сможете использовать все те же функции-члены на вашем stackstring которые вы используете сейчас на std::string, как find_first_of(), append(), и т.д. begin() и end() будет по-прежнему работать нормально, так что вы сможете использовать многие алгоритмы STL.Конечно, этого не будет std::string в самом строгом смысле, но это все равно будет "строка" в практическом смысле, и она все равно будет весьма полезна.

Другие советы

Проблема в том, что std::basic_string имеет параметр шаблона для распределителя.Но std::string не является шаблоном и не имеет параметров.

Таким образом, вы могли бы в принципе использовать экземпляр std::basic_string с распределителем, который использует память в стеке, но это не было бы std::string.В частности, вы не получили бы полиморфизма во время выполнения, и вы не смогли бы передать результирующие объекты в функции, ожидающие std::string.

Ты не можешь.За исключением...

std::string является экземпляром

std::basic_string<class CharType, 
                  class Traits=char_traits<CharType>, 
                  class Allocator=allocator<CharType> >

Предположительно, вы могли бы определить класс распределителя, который использует распределять для управления памятью.Это сработало бы только в том случае, если сам Распределитель и basic_string методы, которые вызывают его прямо или косвенно, - это все inline.A basic_string объект, созданный с помощью этого распределителя, не будет быть a std::string, но он будет вести себя (в основном) подобным образом.Однако это было бы изрядным объемом работы при ограниченной прибыли.В частности, использование этого класса для возврата значений из функции было бы шагом, ограничивающим карьеру.

Я понятия не имею почему вы или кто-то другой захотел бы это сделать.

Я подозреваю, что сделать такую вещь было бы трудно, интересно, почему вы хотите это сделать?Чтобы выделить что-то полностью в стеке, компилятор должен знать во время компиляции, каков точный размер объекта - в вашем примере ему нужно было бы знать не только размер std::string метаданные, но также и размер самих строковых данных.Это не слишком гибко, вам, вероятно, понадобятся разные типы строк в зависимости от размера строковых данных, которые вы хотите в них включить - не то чтобы это было невозможно сделать, просто это немного усложнило бы ситуацию.

  • std::string всегда будет управлять своим внутренним хранилищем с помощью new / delete .
  • Не уверен, почему ваш вопрос содержит реализация строки glibc.Строковая реализация стандартной библиотеки c ++ не имеет ничего общего с glibc ( глибц ).
  • Единственный способ сохранить строку в стеке - это использовать массив символов C в стеке (подобно тому, что описал Shhnap).Но это, вероятно, все равно не то, чего вы хотите :-)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top