shared_ptr<string> pNico(new string("Nico"));
shared_ptr<string> pJutta(new string("Jutta"));
// put them multiple times in a container
vector<shared_ptr<string>> whoMadeCoffee;
whoMadeCoffee.push_back(pJutta);
whoMadeCoffee.push_back(pJutta);
whoMadeCoffee.push_back(pNico);
whoMadeCoffee.push_back(pJutta);
whoMadeCoffee.push_back(pNico);

pNico = nullptr;         
whoMadeCoffee.resize(2);

В конце программы, когда последний владелец строки уничтожается, общий указатель вызывает delete для объекта, на который он ссылается. Такое удаление не обязательно должно происходить в конце области действия. Например, присвоение nullptr значению pNico или изменение размера вектора так, чтобы он содержал только первые два элемента s, приведет к удалению последнего владельца строки, инициализированной с помощью nico.

(из Josuttis, Nicolai M .. "Стандартная библиотека C ++".)

У меня вопрос: почему в вышеупомянутом случае не гарантируется, что память объекта "Nico" будет удалена в конце области видимости?

Хотя если мы сделаем это вместо

whoMadeCoffee.resize(2);
pNico = nullptr;

Память, связанная с "Nico", удаляется.

Может кто-нибудь объяснить разницу?

1
Hemantxoxo 3 Окт 2019 в 19:47

1 ответ

Лучший ответ

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

string("Nico") будет уничтожен, когда счетчик ссылок достигнет 0. В вашем примере он достигает 0 (для Нико) даже до достижения конца области видимости.

Он может жить вне своей области видимости, если вы поделитесь с кем-то другим за пределами вашей текущей области, например, имея функцию, которая возвращает shared_ptr, или вот еще более простой пример:

shared_ptr<string> pNico0(new string(""));
{ 
    shared_ptr<string> pNico1(new string("Nico"));
    pNico0 = pNico1; // pNico0 reference count = 2
}
// pNico0 reference count = 1

Живите на godbolt

4
Oblivion 3 Окт 2019 в 17:30