Создать указатель на кучу в пользовательском конструкторе - PullRequest
0 голосов
/ 27 октября 2019
class Person {
  public:
    int *p_age;
    Person(int);
 };

Person::Person(int age) {
  p_age = new int(age);
}

Я знакомлюсь с управлением памятью в c ++, но пока не уверен, как проверить для себя, какая память создается в стеке по сравнению с кучей. Вот пример: я полагаю, что я создал указатель p_age на куче в пользовательском конструкторе, но прежде чем я столкнусь с какой-либо проблемой позже, есть ли какой-нибудь способ проверить подобные вещи во время выполнения для моего собственногоздравомыслие?

1 Ответ

1 голос
/ 27 октября 2019

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

. в смысле, ваш p_age указывает на int объект с динамической продолжительностью хранения (т.е. в куче) после назначения из new. Однако p_age (указатель, а не объект, на который он указывает) продолжительность хранения зависит от того, как создается его родительский объект типа Person, к которому он относится подобъект, например, с Person person{42}; вТело функции, person и person.p_age будет иметь автоматическую продолжительность хранения (т. е. они находятся в стеке), тогда как *(person.p_age), объект, на который указывает person.p_age, все еще имеет динамическую продолжительность хранения (т. е. живет в куче).

Невозможно проверить, имеет ли объект, на который указывает указатель, динамическую или автоматическую продолжительность хранения во время выполнения. Задача программиста - убедиться, что они не перепутаны, и вы, например, случайно вызываете delete для указателя на объект автоматической длительности хранения. Вот почему вы должны редко использовать new (который всегда создает объекты с динамической длительностью хранения) и вместо этого инкапсулировать каждый объект с динамической длительностью хранения объектом автоматического управления длительностью хранения, например, используя std::unique_ptr, чтобы явные обращения кdelete становятся ненужными.

В частности, в вашем примере, похоже, нет никакой причины для динамического выделения (будь то напрямую с new или через std::unique_ptr) вообще. «Возраст» должен быть частью «Человека», т. Е. Если «Человек» создан или уничтожен, то так же должен быть и его «возраст». Следовательно, p_age должен иметь тип int, а не int*, и его следует просто назначить в конструкторе:

Person::Person(int age) : p_age(age) {
}

, который использует синтаксис списка инициализатора *1036* для непосредственного связыванияинициализировать (а не назначать после инициализации, как в вашем коде) p_age со значением age.

...