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

Создание объекта в стеке/куче?

Следующий код создает объект в стеке:

Object o;

При создании объекта в куче мы можем использовать:

Object* o;

o = new Object();

а не:

Object* o = new Object();

Когда мы разделяем создание объекта кучи над двумя строками и вызываем конструктор во второй строке (o = new object()), означает ли это в первой строке (Object* o), указатель был создан в стеке? Итак, Object o помещает объект в стек, тогда как Object* o помещает указатель на будущий объект в стеке?

Второй вопрос заключается в том, что две строки кода вызывались вне класса. Недавно я прочитал (Глобальное управление памятью в C в стеке или куче?), что глобальные переменные не содержатся в стеке/куче, а на самом деле другая часть памяти? Если это так, может ли Object* o создать указатель, который будет находиться в этой другой части памяти, и он указывает на объект кучи?

4b9b3361

Ответ 1

Собственно, ни один оператор не говорит ничего о куче или стеке:

Object o;

создает объект с автоматическим хранилищем, означающий, что место хранения определяется контекстом, в котором объявлен объект: если код находится в функции, это оказывается стеком вызовов. Но строка также может быть членом класса или, как вы заметили, вне функции/класса.

Чтобы проиллюстрировать, почему это другое:

struct Foo {
    Object o;
};

Foo* pf = new Foo();

Теперь объект pf->o создается в куче, а не в стеке, хотя (или, скорее, потому что) он имеет автоматическое хранилище.

С другой стороны,

Object* p;

просто объявляет указатель, не более того. Хранилище указателей неотличимо от любых других объектов: оно имеет автоматическое хранилище. Кроме того, инициализирующее выражение не влияет на хранилище переменных.

То, что указывает указатель, - совершенно другое дело. Это может быть объект, выделенный для кучи (например, с помощью new), или он может указывать на другой автоматически назначенный объект. Рассмотрим:

Object o;
Object* p = &o;

Ответ 2

С++ предлагает три разных способа создания объектов:

  • Основанные на стеке, такие как временные объекты
  • На основе кучи, используя новый
  • Статическое распределение памяти, такое как глобальные переменные и объекты пространства имен

Рассмотрим ваш случай,

Object* o;
o = new Object();

и

Object* o = new Object();

Обе формы одинаковы. Это означает, что в стек создается переменная o o (предположим, что ваши переменные не относятся к категории 3 выше) и указывает на память в куче, которая содержит объект.

Ответ 3

Две формы одинаковы с одним исключением: временно (Object *) имеет значение undefined, когда создание и присвоение являются отдельными. Компилятор может объединить их вместе, поскольку указатель undefined не особенно полезен. Это не относится к глобальным переменным (если объявление не является глобальным, и в этом случае оно по-прежнему истинно для обеих форм).

Ответ 4

А)

Object* o;
o = new Object();

`` Б)

Object* o = new Object();

Я думаю, что A и B не имеют разницы. В обоих случаях o является указателем на класс Object. оператор new Object() создает объект класса Object из памяти кучи. Оператор присваивания присваивает адрес выделенной памяти указателю o.

Одна вещь, которую я хотел бы упомянуть о том, что размер выделенной памяти из кучи всегда равен sizeof (Object), а не sizeof (Object) + sizeof (void *).

Ответ 5

В обоих примерах локальные переменные типа Object* выделяются в стеке. Компилятор может создавать один и тот же код из обоих фрагментов, если у вас нет возможности обнаружить разницу.

Область памяти для глобальных переменных такая же, как область памяти для статических переменных - она ​​не находится ни в стеке, ни в куче. Вы можете поместить переменные в эту область, объявив их static внутри функции. Следствием этого является то, что экземпляр становится общим для одновременных вызовов вашей функции, поэтому вам нужно внимательно изучить синхронизацию при использовании статики.

Вот ссылка для обсуждения макета памяти запущенной программы C.

Ответ 6

C++ имеет автоматические переменные, а не переменные стека.

Автоматическая переменная означает, что компилятор C++ самостоятельно обрабатывает выделение/освобождение памяти. C++ может автоматически обрабатывать объекты любого класса - независимо от того, имеет ли он динамически распределенные члены или нет. Это было достигнуто благодаря строгой гарантии C++, что деструктор объекта будет вызываться автоматически, когда выполнение выходит из области действия, где была объявлена автоматическая переменная. Внутри объекта C++ может быть много динамических распределений с помощью new в конструкторе, и когда такой объект объявлен как автоматическая переменная - все динамические выделения будут выполнены, а затем освобождены в деструкторе.

Переменные стека в C не могут быть распределены динамически. Стек в C может хранить указатели или фиксированные массивы или структуры - все фиксированного размера, и эти вещи размещаются в памяти в линейном порядке. Когда программа на C освобождает переменную стека - она просто перемещает указатель стека назад и ничего более.

Даже несмотря на то, что программы C++ могут использовать сегмент памяти стека для хранения примитивных типов, аргументов функций или других, - все это решает компилятор C++, а не разработчик программы. Таким образом, концептуально неправильно равнять C++ автоматические переменные и переменные стека C.