Подтвердить что ты не робот

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

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

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

Как создать строку, полностью выделенную в стеке?

4b9b3361

Ответ 1

Я хотел сделать это недавно, и нашел следующий код:

Chronium stack_container.h

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

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

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

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

Ответ 2

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

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

Ответ 3

Вы не можете. За исключением...

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

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

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

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

Ответ 4

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

Ответ 5

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