Когда unique_ptr освобожден? - PullRequest
1 голос
/ 04 октября 2019

В этом коде:

void f(std::unique_ptr<int> q)
{
}

void g()
{
    std::unique_ptr<int> p{new int{42}};
    f(std::move(p));
}

В какой строке p освобождается? Я сказал бы на выходе из функции f, потому что она была перемещена туда с помощью std :: move, но я не уверен и не уверен в этом ответе.

Ответы [ 5 ]

5 голосов
/ 04 октября 2019

В какой строке p освобождается?

p является объектом, и объекты могут быть уничтожены . Немо, что может быть освобождено .

Память, на которую p изначально указывал (выделяется new int{42}), освобождается, когда элемент управления покидает f (когда q отменен).

p само уничтожается, когда контроль оставляет g (в этот момент p равен нулю, то есть не указывает ни на что).

5 голосов
/ 04 октября 2019

В какой строке p освобождается?

В конце области, где она была объявлена, т. Е. Функция g в этом случае. То есть, когда объекты с автоматическим хранением уничтожаются и их память освобождается.

Целое число с динамическим хранилищем, которое вы инициализировали для 42, будет освобождено деструктором q в конце f. Это связано с тем, что ход строительства перешел в собственность.

2 голосов
/ 04 октября 2019

Для ясности измените фрагмент кода следующим образом

#include <iostream>
#include <memory>
#include <utility>

struct A
{
    ~A() { std::cout << "~A()\n"; }
};

void f(std::unique_ptr<A> q)
{
    std::cout << "f() begins\n";
}

void g()
{
    std::cout << "g() begins\n";
    std::unique_ptr<A> p{new A };
    f( std::move( p ) );
    std::cout << "p == nullptr is " << ( p == nullptr ) << '\n';
    std::cout << "g() endss\n";
}

int main() 
{
    std::cout << "Within main()\n";
    g();

    return 0;
}

Вывод программы:

Within main()
g() begins
f() begins
~A()
p == nullptr is 1
g() endss

Таким образом, функция g передала владение указанным объектом функциие. Функция f закончилась и не передала право владения указанным объектом ни другой функции. Итак, в момент выхода из функции f был вызван деструктор.

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

p будет уничтожен при выходе из функции g, как и любая другая переменная с локальной областью видимости. Только в это время он больше не хранит данные;чтобы понять, вам на самом деле не нужна отдельная функция, просто подумайте:

int* n = new int(42);

{
    std::unique_ptr<int> p(n); // p how owns the value pointed to by n
                               // for brevity, I'll say p owns n from now on,
                               // although technically not correct...

    { // opening another scope! (corresponds to function call)
        std::unique_ptr<int> q; // another variable, nothing else is a
                                // function parameter either...

        q = std::move(p);       // this happens, too, when calling a function
                                // at this point, the ownership is transferred to q
                                // q now owns n, p is left with just nothing
                                // (i. e. now holds a null-pointer)
    } // at this point, q is going out of scope; as it is the current
      // owner of n, it will delete it

    // p still is in scope, but it has transferred ownership, remember?

} // at this point, p is destroyed; as it doesn't own anything at all any more
  // it dies without doing anything either...
1 голос
/ 04 октября 2019

Вы передаете права собственности с p на q, поэтому q теперь владеет ресурсом. Поэтому ваше целое число уничтожается, как только уничтожается q, то есть в конце функции f.

Сами уникальные указатели уничтожаются в конце своих областей, то есть pуничтожается, когда g() возвращается и q уничтожается, когда f() возвращается.

См. также этот небольшой пример .

...