Синглтон: почему нет необходимости удалять и не видно отладочное сообщение деструктора - PullRequest
0 голосов
/ 08 февраля 2019

Мой инструктор говорит, что нам не нужно удалять одноэлементный объект, созданный в куче, потому что, когда он выходит из области видимости, его память освобождается и автоматически удаляется.

Если компилятор обрабатывает статические объекты иначе, чем мыне нужно беспокоиться об удалении этого объекта из кучи?

В приведенном ниже коде я думаю, что указатель выходит из области видимости в main, а не сам объект в куче, но в какой-то моментдолжен ли вызываться деструктор объекта, если для этого объекта действительно освобождена память?

Я также пытался добавить функцию-член DeleteObject в main, но не вижу деструктора объекта в вызываемой куче.

, но все еще не видит, как деструктор показывает сообщение на экране.

#include <iostream>
using namespace std;

class Singleton {
public:
static Singleton* GetInstance();
void Show() { cout << "Single object"; }
void DeleteObject();
~Singleton();

private:
static Singleton* psingleton;
Singleton();
};

void Singleton::DeleteObject() {
delete psingleton;
}

Singleton::~Singleton() {
cout << "\n\nAt Destructor";
}

Singleton* Singleton::psingleton = 0;
Singleton::Singleton()
{
//do stuff
}

Singleton* Singleton::GetInstance() {
if (psingleton = NULL ) {
psingleton = new Singleton();
}
return psingleton;
}

int main()
{
Singleton::GetInstance()->Show();
Singleton::GetInstance()->DeleteObject();//another try
return 0;
}

Ожидается, что деструктор объекта покажет сообщение на экране, потому что оно вызывается.

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Я думаю, что ваш инструктор ошибается, приведенный выше код вызовет утечку памяти объектов Singleton

0 голосов
/ 08 февраля 2019

Мой инструктор говорит, что нам не нужно удалять одноэлементный объект, созданный в куче, потому что, когда он выходит из области видимости, его память освобождается и автоматически удаляется.

Это то, что компилятор обрабатывает статические объектыиначе что нам не нужно беспокоиться об удалении этого объекта из кучи?

Ваш инструктор ошибается.Динамически размещенный объект (например, созданный с помощью оператора new) будет освобожден только в том случае, если он специально уничтожен (например, с использованием соответствующего оператора delete).

Не имеет значения, является ли указатель на объектстатическая переменная.

Что происходит с большинством современных операционных систем, так это то, что операционная система освобождает память, используемую программой, когда программа завершается (обычно или ненормально).Однако это не вызывает вызов деструктора динамически размещаемого объекта.Если вы полагаетесь на вызываемый деструктор (а не на восстановление памяти), то вам нужно убедиться, что деструктор вызывается до завершения программы.Например, если объект управляет системным ресурсом, таким как мьютекс.

Стандарт C ++ не требует, чтобы динамически размещенные объекты освобождались при завершении программы.И большинство (если не все) современные операционные системы (Unix, Windows и т. Д.), Которые освобождают память для существующих процессов, возвращают память, не будут вызывать деструкторы динамически размещаемых объектов.

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

Есть, конечно,методы, которые можно использовать для обеспечения освобождения динамически размещаемых объектов (например, сохранить указатель на эти объекты в std::unique_ptr).Статический std::unique_ptr<T> будет уничтожен при завершении программы, а его деструктор автоматически уничтожит любой динамически размещенный объект, которым он управляет.(Конечно, есть способы предотвратить это, например, позвонив по номеру std::abort()).

0 голосов
/ 08 февраля 2019

Это потому, что у вас есть ошибка.Это здесь

Singleton* Singleton::GetInstance() {
     if (psingleton = NULL) {
        psingleton = new Singleton();
    }
    return psingleton;
}

Не создает объект, потому что psingleton = NULL всегда приводится к false.Вместо этого вы хотите if (psingleton == NULL) {.

. С этим исправлением для меня в MSVC будет вывод:

Один объект

В деструкторе

... что происходит из-за вызова Singleton::GetInstance()->DeleteObject();, а не потому, что программа закончилась.


Я думаю, что указатель выходит из области видимости в mainи не объект в самой куче, но в какой-то момент деструктор объекта должен быть вызван, если действительно память освобождена для этого объекта?

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

...