в C RAII всегда выделяет объекты в стеке или он когда-либо использует кучу?

#c #raii

#c #raii

Вопрос:

Мне интересно, всегда ли RAII выделяет в стеке, или компилятор когда-либо использует кучу для больших объектов (а затем, возможно, добавляет токен в стек как своего рода напоминание о том, когда следует уничтожить соответствующий объект, выделенный в куче)?

ОБНОВЛЕНИЕ: По-видимому, этот вопрос был сочтен неясным. Возможно, пример кода прояснит это:

В этом коде:

 void dosomething() {
    MyClass myclass();
}
  

Предполагая, что компилятор не оптимизировал такой тривиальный пример, всегда ли экземпляр MyClass, который создается таким образом, выделяется в стеке, или куча когда-либо используется?

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

Комментарии:

1. RAII и выделение «стека» — довольно ортогональные понятия.

2. Распределение стека — это распределение стека, в этом все дело. Точка.

3. Где RAII тогда выделяет? Может ли пользователь указать?

4. вам следует прочитать о динамическом и автоматическом выделении , RAII это не противоречит ни одной из этих двух концепций, вы на неверном пути .

5. @Magnus RAII нигде не выделяет. Это связано с тем, что происходит в начале и в конце срока службы объекта, независимо от того, где он был выделен.

Ответ №1:

То, как вы говорите о RAII, звучит так, будто у вас сложилось неправильное представление о самой фундаментальной идее того, что такое RAII. RAII (также известный как SBRM — управление ресурсами, привязанными к стеку, поэтому RAII на самом деле не полностью ортогональен, по крайней мере, концепции стека) — это, по сути, стиль программирования.

Программы, написанные с использованием RAII, могут и часто выделяют память из свободного хранилища. Однако такие выделения обрабатываются объектом некоторого класса. Когда объект уничтожается, выполняется деструктор класса, и это освобождает динамически выделяемую память.

Например, типичный string объект будет содержать только небольшой объем данных, таких как указатель на содержимое строки и одно или два целых числа для отслеживания размера строки. Когда вы создаете строку, она выделяет некоторое пространство из свободного хранилища для хранения фактических данных. Когда строка уничтожается, она автоматически освобождает эти данные. В некоторых случаях у него будет некоторая логика, позволяющая избежать такого выделения свободного хранилища для небольших строк путем выделения небольшого (фиксированного) объема пространства в самом объекте string, но это не меняет основной идеи.

Итак, реальный ответ — это квалифицированное «да». Да, довольно часто имеется небольшой объект, содержащий указатель на некоторые данные, выделенные в куче. Да, объект освободит эту память, когда сам объект будет уничтожен. Но нет, это не то, что компилятор делает за вас. Скорее, это то, что вы делаете при проектировании и реализации своих классов.

Комментарии:

1. Таким образом, сам экземпляр класса находится в стеке, хотя его члены могут представлять собой смесь аналогичных элементов на основе RAII и традиционных элементов на основе new / delete? Другими словами, когда я говорю MyClass myclass(); этот объект сам был в стеке, даже если его внутренности не обязательно были?

2. Ответ на ваш основной вопрос — да. Большая часть кода должна просто определять объекты с автоматическим хранением. К сожалению, ваш пример относится к «самому неприятному синтаксическому анализу»: MyClass myclass() объявляется функция с именем myclass с возвращаемым типом MyClass . Чтобы определить объект, вам нужно опустить круглые скобки: MyClass myclass; .