У вас есть два объекта, которые статически, указатель с именем p1
и экземпляр типа p
имени p2
.
В вашей программе есть два места, где могут возникать динамические распределения: в конструкторе класса p
и при инициализации статической переменной p1
.
Статически выделенные объекты p1
(указатель) и p2
(экземпляр класса) существуют до тех пор, пока программа запускается. Важно выделить указатель p1
, содержащий только адрес из экземпляра класса по этому адресу. (Этот экземпляр будет создан во время выполнения на new p()
). Указатель и «указатель» могут иметь независимые времена жизни; оба существуют независимо друг от друга. Указатель может существовать и не указывать на что-либо, и объект, созданный вызовом new p()
, может существовать дольше, чем любой указатель на него.
Ниже представлена последовательность событий, которая разворачивается при стартовой программе. Инициализация статических переменных указана в разделе 3.6.2 стандарта C++ 11.
Распределение переменных с статической продолжительностью хранения, здесь p1
и p2
. Рабочая модель заключается в том, что память является частью программы.
Обнуление этих переменных. «Переменные со статической продолжительностью хранения [...] должны быть инициализированы нулем перед любой другой инициализацией». Указатель p1
, а также память, в которой теперь находится p2
, состоят из байтов, которые все равны нулю.
Dynamic (т.е. времени выполнения) инициализации этих переменных в порядке их определения:
- Инициализация указателя
p1
начинается с вызова new p()
.
- Память для нового объекта типа
p
распределяется динамически («на куче») со стандартным распределителем. Содержимое памяти не инициализировано и неизвестно. Объект не имеет имени, поэтому назовем его x
.
x
'конструктор выполнен с целью его инициализации.
- Конструктор присваивает значение до сих пор неинициализированной переменной-члену
x.q
. x.q
является частью x
и как таковой находится в памяти, динамически распределенной ранее.
- Правая сторона задания - это еще один вызов
new
, на этот раз для int. Стандартный распределитель динамически выделяет память для int, которая инициализируется с помощью 100.
- Возвращаемое значение
new
является адресом памяти, в котором находится int, который присваивается указателю int x.q
.
x
'конструктор возвращает, и new p()
возвращает адрес памяти, где x
проживает.
- Это возвращаемое значение присваивается до сих пор нулевым инициализированным
p1
, которое теперь указывает на неназванный экземпляр p
, который мы назвали x
.
- Инициализация
p2
. Выполняется конструкторp2
, который выполняет то же самое, что и конструктор x
: Он вызывает new
для int, который вызывает распределение динамической памяти, инициализирует его значением 100 и присваивает адрес ячейки памяти int p2.q
.
В результате, как далеко, как ячейки памяти и отношения между объектами обеспокоены, как показано на приведенной ниже схеме.
Это должно помочь ответить на ваши вопросы:
p1
находится в «статическом сегменте», если вы хотите, но объект он указывает было динамически выделяемой во время выполнения позвоните по телефону new
.
- Статический объект
p2
не содержит «динамически распределенная переменная элемента q». Это предложение смущает переменную-член - указатель с именем q
- с объектом , которому q
баллов,, который является динамически выделяемым int.Переменная-член q
хранится везде, где хранится содержащийся экземпляр класса p
; Фактически, это является единственными данными в этом случае. (Попробуйте sizeof(p)
!) Объект, к которому относится элемент любого экземпляра q
, - это всегда динамически выделяемый int (ну, пока какой-то злонамеренный программист не присвоит вашему публике другое значение q
).
Это будет представлять собой утечку памяти, поскольку динамически выделенный объект, адрес которого был утрачен никогда не могут быть удалены программой.
Нет, и нет. Что еще более важно, вам все равно. –
Почему вы не запускаете код и не видите сами? – CrakC
@CrakC это, как правило, не очень хорошая идея с C++. – Quentin