Удаление объекта из кучи

В основной функции я создаю объект, используя new, и не удаляю его. Я надеюсь, что пространство кучи будет очищено после завершения процесса. Ниже приведен пример кода, где объект класса A является переменной-членом класса B. Класс B также имеет мультикарту в качестве переменной-члена.

    Class A
{
Public:
A(); //have definition in cpp file
~A();//have definition in cpp file
Private:
Int a;
};

Class B{
Private:
Std::multimap<string,string> map_test;
Public:
A a;
B(); //have definition inn cpp file
~B();//does not have any definition in cpp file
};

int main()
{
B *b = new B();
/* code section where it fills some 1000 key value pairs in the multimap
for some purpose */
return 0;

}

Мое понимание:

  1. Даже если я не удаляю объект здесь, это не создаст никакой проблемы, так как пространство кучи будет очищено после завершения процесса. Так как моя область действия программы ограничена, как указано выше, и никто больше не собирается использовать это повторно. хорошо или плохо не использовать delete? Что вы предлагаете по этому поводу?
  2. Он должен вызывать деструктор объекта по умолчанию, который затем вызывает неявный многостраничный деструктор. Так что нет необходимости явно очищать мультикарту. Пожалуйста, исправьте меня, если я ошибаюсь.
  3. В родительском классе он просто объявляет деструктор и не имеет никакого определения. Так будет ли он вызывать неявный деструктор или он будет игнорировать его вызов? (Нет причин не определять его, просто требовать лучшего понимания.)
  4. Если он вызывает неявный деструктор в случае родительского класса, должен ли он вызвать деструктор дочернего класса, который здесь определен?
  5. Поскольку объект родительского класса создается с использованием new, он будет создан в куче. Тогда именно там будут храниться переменные-члены этого родительского объекта. Например, объект «a» является переменной-членом и, глядя на объявление этого члена объект, похоже, будет создан в стеке. Я просто запутался здесь, как происходит точное создание памяти родительского объекта и его дочернего объекта. Можете ли вы помочь мне понять это?

1

Решение

  1. Да, пока ваш объект создан в main.
    Однако, если вы когда-либо захотите изменить это и, например, создать несколько экземпляров B, или использовать его внутри другого класса, и т. Д. И т. Д., Это другая история. Кроме того, инструменты проверки памяти, такие как valgrind, будут давать вам ложные срабатывания при новом удалении без удаления, которое вы будете склонны игнорировать. Но тогда вы можете игнорировать настоящую утечку памяти, если она станет привычкой.

  2. Правильно, теперь, если это было map<string, string*> тогда вам, скорее всего, придется убирать

  3. Это вызовет деструктор по умолчанию

  4. Да, это будет

  5. Я думаю, вы спрашиваете, где хранятся переменные членов базового класса? Они также хранятся в куче. Они предшествуют полям производного класса в памяти.

1

Другие решения

Вы задали много вопросов.

Сначала рекомендуется всегда очищать вашу память, даже если процесс завершает работу и очищает всю память (как она это делает). Всегда справляйся … это легко сделать, используя shared_ptr …

Деструкторы всегда вызываются в правильном порядке, однако ваша мультикарта является опасностью, поскольку вы должны очищать элементы в мультикарте, так как если вы храните указатели, это может вызвать серьезную утечку

0

  1. Большинство ОС очищают пространство кучи процесса при выходе из процесса. Я не удивлюсь, если есть множество встроенных ОС, где это не так, плюс это все еще плохая практика, поскольку у вас есть утечка памяти.
  2. По мере утечки памяти никакие деструкторы не будут вызываться. Тем не менее, если вы не реализуете деструктор и полагаетесь на сгенерированный компилятором деструктор по умолчанию, вы также не должны объявлять его — на самом деле я удивлен, что вы не получаете ошибку компоновщика. И да, деструктор по умолчанию для мультикарты будет удалять содержимое мультикарты, если вы соблюдаете требования контейнера к семантике значений (т. Е. Нет необработанных указателей).
  3. Это плохая практика, и как программист вы должны быть уверены, что всегда правильно управляете своими ресурсами. Кроме того, я не вижу причин для выделения кучи bВы можете просто создать объект в стеке, и вам не придется думать об управлении ресурсами.
  4. Если вы объявите это, вам придется предоставить реализацию, так как объявление деструктора неявно отключит деструктор, сгенерированный компилятором. Вот почему я сказал выше, что я удивлен, что вы не получаете ошибку ссылки.
  5. Компилятор позаботится об уничтожении базовых классов, обходя иерархию и вызывая деструкторы в обратном порядке построения.
  6. Нет, весь объект, содержащий как A, так и B, будет создан в куче — поэтому вы можете присвоить псевдониму указатель на B в качестве указателя на A и взаимодействовать с производным классом, как если бы это был базовый класс.
0

Факт: в C ++ нет встроенной (под таблицей) сборки мусора, хотя есть много вещей, которые могут навязать какую-то сборку мусора.

Таким образом, в вашем коде у вас есть утечка памяти. В конце области, в которой вы выделяете B, выделенная вами память не является free’d.

Просматривая ваш список вопросов:

  1. Нет, если вы не удалите указатель, память не будет свободна. Есть несколько вещей, которые вы можете сделать по этой теме:

    • Использовать RAII идиома (Получение ресурсов — это инициализация), то есть использование объектов для управления памятью:
    • Используйте умные указатели: эти конструкции обеспечивают RAII (наиболее распространенным, на мой взгляд, является std::shared_ptr а также std::unique_ptr) и убедитесь, что память, за которую они отвечают, правильно free’d.
  2. Это зависит. Если вы распределили объекты с помощью new оператор, затем вставил их в карту, но они не упоминаются где-либо еще, то вы должны вручную удалить каждую запись карты. Это не применяется в этом случае, потому что типы карт не указатели.

  3. Класс может даже пропустить объявление деструктора. Если они опущены, компилятор генерирует деструкторы (но также оператор присваивания копии, конструктор копирования и конструктор по умолчанию).

  4. Отредактировано: зависит, если вы объявили участника A a;Вам не нужно явно удалять его, его деструктор будет вызываться, когда классу, который объявляет его как член, вызывается деструктор. но если это указатель, который вы разместили (например, в конструкторе), то вы должны удалить его в деструкторе.

  5. Как только вы используете динамическое выделение памяти для объекта, все Объект находится в куче, независимо от того, как его члены объявлены.

0
По вопросам рекламы [email protected]