Как работает std :: unique_ptr, когда он выходит из области видимости после удаления принадлежащего ему объекта? - PullRequest
1 голос
/ 21 июня 2019

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

Рассмотрим следующий фрагмент кода:

#include <iostream>
#include <memory> // for std::unique_ptr

class Resource
{
public:
    Resource() { std::cout << "Resource acquired\n"; }
    ~Resource() { std::cout << "Resource destroyed\n"; }
};

int main()
{
    Resource* res = new Resource;
    std::unique_ptr<Resource> res1(res); // Resource created here
    delete res;

    std::cout << "res1 is " << (static_cast<bool>(res1) ? "not null\n" : "null\n");

    return 0;
}

Это печатает:

$ ./a.out 
Resource acquired
Resource destroyed
res1 is not null
Resource destroyed

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

Но давайте предположим, что мы все равно вручную удалим ресурс (не устанавливая его в null после), как в приведенном выше коде.Затем, когда res1 выходит из области видимости, не пытается ли он удалить то, что уже было освобождено?

1 Ответ

5 голосов
/ 21 июня 2019

Да, unique_ptr попытается удалить объект после того, как он выйдет из области видимости в этом случае.Фактически, пример, который вы показали выше, является идеальным способом проиллюстрировать одно из ключевых свойств unique_ptr: если у вас есть ресурс, управляемый unique_ptr, вы не должны пытаться управлять этим ресурсом самостоятельно вне unique_ptr.В конце концов, контракт с unique_ptr означает, что unique_ptr владеет исключительно ресурсом, поэтому, если вы берете этот ресурс и освобождаете его самостоятельно, вы нарушаете контракт.

Другими словами, чтоunique_ptr делает это немного сильнее, чем «позволяет нам не беспокоиться о необходимости вручную удалять ресурс».Скорее, он принимает на себя полную и исключительную ответственность за управление ресурсом.

Подобные проблемы могут возникнуть, скажем, с shared_ptr, который предполагает, что все владение ресурсом распределяется между различными shared_ptr сresource.

Если вы хотите явно освободить ресурс перед возвратом функции, используйте функцию reset:

res1.reset(); // Cleans up the resource.
...