Распределяется ли этот тип памяти в куче или стеке? - PullRequest
4 голосов
/ 09 января 2009

В контексте C ++ (не то, чтобы это имело значение):

class Foo{
    private:
        int x[100];
    public:
        Foo();
}

То, что я узнал, говорит мне, что если вы создадите экземпляр Foo следующим образом:

Foo bar = new Foo();

Затем массив x выделяется в куче, но если вы создали экземпляр Foo, вот так:

Foo bar;

Затем он создается в стеке.

Я не могу найти ресурсы в Интернете, чтобы подтвердить это.

Ответы [ 5 ]

10 голосов
/ 09 января 2009

Строго говоря, согласно стандарту, объект не обязательно должен существовать в стеке или куче. Стандарт определяет 3 типа «продолжительности хранения», но не указывает, как именно должно быть реализовано хранилище:

  1. статическая продолжительность хранения
  2. длительность автоматического хранения
  3. динамическая продолжительность хранения

Автоматическая продолжительность хранения обычно (почти всегда) реализуется с использованием стека.

Динамическая продолжительность хранения обычно реализуется с использованием кучи (в конечном итоге через malloc()), хотя она может быть переопределена даже пользователем компилятора.

Статическая длительность хранения - это то, что обычно называют глобальными (или статическими). ​​

В стандарте есть, что сказать об этих вещах (ниже приводятся выдержки из различных битов 3,7 - Длительность хранения):

Статическое и автоматическое время хранения связаны с введенными объектами по декларациям (3.1) и неявно созданный реализацией (12.2). Динамическая продолжительность хранения связанные с объектами, созданными с оператор новый (5.3.4).

...

Все объекты, которые не имеют динамического длительность хранения, ни местные статическая продолжительность хранения. Хранение для этих объектов будет продолжаться для продолжительность программы (3.6.2, 3.6.3).

...

Локальные объекты явно объявлены автоматически или зарегистрируйтесь или не заявили явно статический или внешний имеют автоматический срок хранения. Хранение для эти объекты длится до блока в из которых они созданы выходы.

...

Объекты могут создаваться динамически во время выполнения программы (1.9), используя новые выражения (5.3.4) и уничтожены используя delete-выражения (5.3.5). A C + + реализация обеспечивает доступ к динамическому хранилищу и управление им через функции глобального распределения оператор новый и оператор новый [] и глобальные функции освобождения оператор удаления и оператор удаления [].

...

Библиотека обеспечивает по умолчанию определения для глобального распределения и функции освобождения. Немного глобальное распределение и освобождение функции сменные (18.4.1)

И, наконец (относительно массива в вашем примере класса):

3.7.4 Продолжительность подобъектов [basic.stc.inherit]

Продолжительность хранения подобъектов-членов, подобъектов базового класса и элементов массива равна продолжительности их завершения объект (1.8).

10 голосов
/ 09 января 2009

Учитывая небольшую модификацию вашего примера:

class Foo{
    private:
        int x[100];
        int *y;
    public:
        Foo()
        {
           y = new int[100];
        }
        ~Foo()
        { 
           delete[] y; 
        }

}

Пример 1:

Foo *bar = new Foo();
  • x и y находятся в куче:
  • sizeof (Foo *) создается в стеке.
  • sizeof (int) * 100 * 2 + sizeof (int *) находится в куче

Пример 2:

Foo bar;
  • х в стеке, а у - в куче
  • sizeof (int) * 100 в стеке (x) + sizeof (int *)
  • sizeof (int) * 100 находится в куче (y)

Фактические размеры могут незначительно отличаться из-за выравнивания класса / структуры в зависимости от вашего компилятора и платформы.

7 голосов
/ 09 января 2009

Объект типа Foo принимает размер 100 дюймов, сохраненный в последовательности. Если вы создадите его в стеке, вы получите все это в стеке. Если вы сделаете это с новым, он будет в куче как часть объекта.

Это часть спецификации языка, я не уверен, какой у вас вопрос.

2 голосов
/ 09 января 2009

Да, массив элементов x будет создан в куче, если вы создадите объект Foo в куче. Когда вы выделяете динамическую память для Foo, вы запрашиваете память длиной sizeof(Foo) (плюс, возможно, некоторые накладные расходы памяти, но давайте пока проигнорируем это), что в вашем примере кода предполагает размер 100 int с , Это имеет значение , которое соответствует сроку службы объектов типа Foo (и их внутренних данных) для пересечения областей действия.

Если вы не создаете объект Foo в куче, а внутренний массив Foo не является указателем, для которого вы выделяете память с помощью new в конструкторе Foo, тогда этот внутренний массив будет создан в стеке. Опять же, это должно иметь место для автоматической очистки массива без каких-либо delete s, когда заканчивается область. В частности,

struct Foo {
    int* y;
    Foo() : y(new int()) { }
    ~Foo() { delete y; }
};

создаст y в куче независимо от того, был ли объект Foo создан в стеке или в куче.

1 голос
/ 09 января 2009

Вы имеете в виду

Foo* bar = new Foo(); 

Полагаю. То, что создано в куче.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...