Удаление динамически размещаемых объектов с помощью частных деструкторов - PullRequest
2 голосов
/ 14 октября 2019

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

Я попробовал это, и да, это не такне позволяет создать экземпляр объекта в стеке. Но когда я создавал экземпляр динамически распределенного экземпляра и пытался удалить объект (или это вызвало бы утечку) - я продолжал получать предупреждение о том, что деструктор является закрытым.

Как правильно управлять памятью динамически распределенного объекта, который имеетчастный деструктор?

Ответы [ 4 ]

6 голосов
/ 14 октября 2019

Подобно доступу к любой другой закрытой функции-члену, вы должны сделать это в функции-члене или в функции друга. Пример:

class foo {
    ~foo(){}
public:
    static void del(const foo* ptr)
    {
        delete ptr;
    }
};

Или даже лучше, заставить клиента использовать умный указатель:

class foo {
    ~foo(){}
    struct deleter {
        void operator()(const foo* ptr)
        {
            delete ptr;
        }
    };
public:
    static std::unique_ptr<foo, deleter> make(/*args*/)
    {
        return {new foo(/*args*/), {}};
    }
};
3 голосов
/ 14 октября 2019

Предоставление функции удаления работает до степени контроля доступа, но заставляет пользователей вашего класса везде использовать пользовательские средства удаления. Более кратко просто подружиться со стандартным средством удаления по умолчанию:

struct Foo {
private:
    friend std::default_delete<Foo>;
    ~Foo() = default;
};

auto p = std::make_unique<Foo>(); // Works out of the box
1 голос
/ 14 октября 2019

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

Итак, я предполагаю, что вашобъект управляет собственной жизнью;например, возможно, он поддерживает счетчик ссылок, а затем вызывает delete this в методе release(), когда счетчик ссылок становится равным 0. Затем ответ на вопрос «как правильно управлять временем жизни объекта», как user объекта - это "правильно использовать объект", так что объект будет освобожден, когда наступит подходящее время.

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

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

Вот один пример:

class Example {
public:
    void kill_me() { // a public function
        delete this; // is allowed to delete
    }
private:
    ~Example() {}    // private destructor
};

int main() {
    Example* e = new Example;
    e->kill_me();
}
...