Не должно use_count()
быть 2 после лямбда-определения
Это:
--- define lambda ---
ptr: refs = 2, val = 0
, а затем1 внутри лямбды?
Это:
--- run lambda ---
ptr: refs = 1, val = 1
Часть, в которой вы запутались, не имеет ничего общего с лямбдами.Вы можете получить тот же эффект, создав простую копию общего указателя:
std::shared_ptr<Foo> ptr = std::make_shared<Foo>( 0 );
logPtr( ptr );
std::cout << "--- define lambda ---\n";
auto cpy = ptr;
logPtr(ptr);
std::cout << "--- reset ptr ---\n";
ptr.reset();
logPtr(ptr);
// run "lambda"
{
std::cout << "--- run lambda ---\n";
if (cpy) {
cpy->val++;
}
logPtr( cpy );
std::cout << "--- end lambda ---\n";
}
logPtr( ptr );
То, что вам не хватает, - это семантика reset()
.Как объясняет cppreference , он
Освобождает владельца управляемого объекта, если таковой имеется.
Что означает
Если *this
уже владеет объектом, а является последним shared_ptr
, владеющим им , объект уничтожается с помощью принадлежащего ему средства удаления.
В вашем коде изначально естьдва общих указателя, совместно использующих право собственности на указанный объект.
После ptr.reset()
первый указатель перестает быть владельцем.Сбрасывается обратно на null
/ 0
.Тем не менее, второй указатель (копия внутри лямбды) по-прежнему является владельцем и поддерживает ссылочный объект живым (теперь с use_count
из 1).
Остальная часть вашего кода просто исследует два разных указателя:Один все еще владеет объектом, а другой ничего не имеет.
Эквивалентный код с использованием необработанных указателей будет выглядеть так:
Foo *ptr = new Foo(0);
Foo *cpy = ptr; // create a copy
ptr = null; // "reset" the first pointer
logPtr(cpy); // examine the copy
delete cpy; // release the object through the last active pointer