Как работает счетчик декремента умного указателя?
Ниже приведен пример кода для общего указателя. Я определяю общий указатель внутри области фигурных скобок. sp1 инициализируется новым A (счетчик = 1), а sp1 назначается sp2 (копирование и / или назначение увеличивают счетчик на 1, поэтому counter = 2). Я всегда думал, что деструктор A вызывается, когда счетчик становится 0. Но в моем случае, умный указатель, когда вот-вот выйдет из области видимости (через фигурную скобку), счетчик равен двум.
У меня вопрос: кто менял счетчик с 2 на 0?
#include <iostream>
#include <memory>
using namespace std;
class A{
public:
~A(){
std::cout << "~A" << std::endl;
}
};
int main(){
{
shared_ptr<A> sp1 (new A);
shared_ptr<A> sp2 = sp1;
std::cout << "sp1 count = " << sp1.use_count() << std::endl;
std::cout << "sp2 count = " << sp2.use_count() << std::endl;
}
return 0;
}
РЕДАКТИРОВАТЬ: ссылка на бумагу на смарт-указатель
выход:
sp1 count = 2
sp2 count = 2
~ A
2 ответа
Когда ваш код доходит до конца main, деструктор для обоих sp1
а также sp2
run, который уменьшает счетчик до нуля - это ОЧЕНЬ важная часть общих указателей, что деструктор уменьшает счетчик ссылок и, таким образом, когда "ничего" не остается, вызывается деструктор фактического общего объекта.
Разрушитель shared_ptr
будет иметь такую логику, как это:
counter--; // Should be atomic!
if (counter == 0)
{
delete owned_thing;
}
Лучшим примером (ИМО) будет что-то вроде этого:
int main()
{
std::shared_ptr<A> sp1{new A};
std::cout << "1: sp1.use_count() = " << sp1.use_count() << '\n';
{
std::shared_ptr<A> sp2 = sp1;
std::cout << "2: sp1.use_count() = " << sp1.use_count() << '\n';
std::cout << "2: sp2.use_count() = " << sp2.use_count() << '\n';
}
std::cout << "3: sp1.use_count() = " << sp1.use_count() << '\n';
}
Вывод из этой программы должен быть (используя ваш класс с его деструктором):
1: sp1.use_count () = 1 2: sp1.use_count () = 2 2: sp2.use_count () = 2 3: sp1.use_count () = 1 ~ A
Сначала вы создаете общий указатель и инициализируете его, делая счетчик использования 1
, Затем вы вводите новую область действия и создаете в ней новый общий указатель, инициализируя его (используя конструктор копирования общих указателей) со старым указателем, что приводит к счету использования обоих указателей. 2
, Затем второй общий указатель выходит из области видимости, а деструктор общего указателя уменьшает количество использования на единицу. Наконец, второй общий указатель выходит из области видимости, так как main
функция возвращает, и счетчик использования уменьшается на sp1
деструктор. Теперь он достиг нуля, и содержащийся в нем указатель удаляется, что приводит к A
деструктор вызывается.