Удалить производный класс с указателем стека?

Таким образом, память стека нельзя освободить вручную с помощью удаления, потому что это каким-то образом вызывает UB. Но при создании объекта производного класса задействовано ключевое слово «новое». Скажите, например:

void some_function(){
    Base* base;
    base = new Derived;
}

Поскольку задействовано «новое», находится ли base = new Derived в куче? И если да, то память, где он находится, нужно снова освобождать вручную? Или он находится в стеке и память все равно освободится после завершения программы?


person lo tolmencre    schedule 31.03.2015    source источник
comment
1) Выделенная память находится в куче. 2) Его следует удалить вручную. Лучшим подходом является использование интеллектуальных указателей, таких как std::unique_ptr или std::shared_ptr. 3) Когда программа завершает работу, память освобождается. Но вы продолжаете выделять память, и если вы не удалите ее, произойдет утечка памяти.   -  person Jagannath    schedule 01.04.2015


Ответы (2)


Правило таково: Каждый раз, когда вы используете new, вы должны освобождать память с помощью delete. Единственным исключением является так называемое "размещение new", которое используется редко (см. комментарии).

В вашем случае указатель с именем base сам находится в стеке. Однако то, на что он указывает, выделяется в куче.

Когда ваша программа завершится, вся ее память будет освобождена ядром. Неважно, где и как была выделена память.

(Примечание для педантов: я использую здесь «стек» и «кучу» в общеупотребительном смысле, несмотря на то, что эти термины не упоминаются в стандарте C++.)

person Greg Hewgill    schedule 31.03.2015
comment
Исключений нет, кроме размещения new. После размещения new следует очистить с помощью явного вызова деструктора, а не delete. - person Ben Voigt; 01.04.2015
comment
@BenVoigt: Хороший улов! - person Greg Hewgill; 01.04.2015
comment
Ждать. Освободятся ВСЕ? Я думал, что выделенная память кучи останется выделенной до тех пор, пока система не перезагрузится, если она не будет освобождена. - person lo tolmencre; 01.04.2015
comment
@lotolmencre: Нет. Вся память кучи, выделенная вашей программой, будет освобождена, когда ваша программа завершится. Конечно, если ваша программа не завершается (например, если это что-то вроде сетевого сервера, предназначенного для работы в течение длительного времени), то эта память остается выделенной, пока ваша программа активна. - person Greg Hewgill; 01.04.2015
comment
Это означает, что если мне все равно нужны все экземпляры, пока программа работает, мне не нужно на самом деле проходить через хлопоты, чтобы удалить их все снова? Хотя это звучит как небрежная практика. - person lo tolmencre; 01.04.2015
comment
@lotolmencre: Это правильно. Небрежно это или нет, зависит от вашей точки зрения. - person Greg Hewgill; 01.04.2015

Имея дело с указателями, не путайте память, которую занимает указатель, с памятью, на которую указывает указатель.

В вашей функции base является локальной переменной функции, и она будет очищена, когда выйдет за пределы области видимости. Однако память base не указывает на волю.

Before allocation: 
--------
| base |
--------
freed at end of scope

After allocation:
--------                    ---------------
| base | ===============>   | new Derived |
--------                    ---------------
freed at end of scope       Will not be freed

Однако, если вы добавите delete base; в свою функцию:

--------                    ---------------
| base | ===============>   | new Derived |
--------                    ---------------
freed at end of function    freed by "delete base;"
person Bill    schedule 31.03.2015
comment
Хорошо, я вижу. Большое спасибо - person lo tolmencre; 01.04.2015