Как выделить std::string в стеке с помощью реализации строки glibc?
int main(void)
{
std::string foo("foo");
}
Я понимаю, что в приведенном выше коде используется распределитель по умолчанию для вызова new. Поэтому, даже если std::string foo выделен в стеке, внутренний буфер внутри foo выделяется в куче.
Как создать строку, полностью выделенную в стеке?
Ответы
Ответ 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). Но это, вероятно, не то, что вы хотите в любом случае: -)