Уничтожение одного shared_ptr по одному

Я пытаюсь уничтожить shared_ptr по одному, но когда я уничтожаю последний указатель, use_count () сходит с ума. Соблюдайте мой код:

#include <iostream>
#include <memory>int main() {

int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);

myPtr.~__shared_ptr();

}

Произведет следующий вывод в отладчике:

myPtr value: 5  myPtr.use_count():8787448 // Or some other large int

Я надеялся на окончательное уничтожение, которое установит use_count () равным 0 и освободит память для целого числа. Похоже, ничего этого не происходит.

Я мог бы if () заявить это, когда use_count () == 1, но это кажется очень не элегантным. Кто-нибудь знает другое решение?

-2

Решение

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

Как это сделать, используя станд :: weak_ptr это предназначено для работы с станд :: shared_ptr так что вы можете отслеживать, был ли объект уничтожен.

Вот:

#include <memory>
#include <iomanip>
#include <iostream>

int main()
{
// weak_ptr is only convertable to a shared_ptr if the shared_ptr
// usage count is > 0
std::weak_ptr<int> wp;

{
std::shared_ptr<int> ptr = std::make_shared<int>(5);
wp = ptr; // link weak_ptr to shared_ptr

if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "Before: use count > 0: "<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "Before: Destroyed\n";
}
// ptr goes out of scope here
}

if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "After: use count > 0: "<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "After: Destroyed\n";
}
}

В основном, если связанный станд :: shared_ptr по-прежнему содержит ссылку на объект, то связанный станд :: weak_ptr может быть преобразован в станд :: shared_ptr с помощью станд :: weak_ptr :: замок. Если это не удается, то связанный станд :: shared_ptr больше не указывает на общий объект — он был уничтожен.

2

Другие решения

Я пытаюсь уничтожить shared_ptr один за другим,

Я понятия не имею, что это значит, но …

myPtr.~__shared_ptr();

Никогда, никогда, никогда не делай этого.

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

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

Стандарт конкретно указывает, что этот точный сценарий — неопределенное поведение, в 12.4 [class.dtor]:

Как только деструктор вызывается для объекта, объект больше не существует; поведение не определено, если
деструктор вызывается для объекта, время жизни которого истекло (3.8). [Пример: если деструктор для
автоматический объект вызывается в явном виде, и блок впоследствии остается таким образом, который обычно
вызвать неявное уничтожение объекта, поведение не определено. — конец примера]

Еще хуже, вы используете деструктор для базового класса myPtr так ты только уничтожаешь часть объекта. Это означает, что у вас есть объект, часть которого мертва, а часть жива, а затем в конце области действия его снова убивают. Ни при каких обстоятельствах это никогда не может быть правильным. Когда-либо.

Я надеялся на окончательное уничтожение, которое установит use_count () равным 0 и освободит память для целого числа. Похоже, ничего этого не происходит.

Ваш вывод неверен. Это, вероятно, происходит, но если объект уничтожен и память освобождена, то попытка взглянуть на него приводит к бессмысленным результатам. Вы не можете спросить зомби, как его зовут, он ответит «BRAINZZZZ!» вместо того, чтобы говорить вам что-нибудь полезное. И есть свои мозги. Теперь ты мертв. Не играй с зомби.

Кроме того, как Нил Кирк комментирует выше, это также неправильно:

int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);

Вы создаете int в кучу, то вы создаете копия об этом в куче, которая будет управляться shared_ptr, shared_ptr владеет int который имеет то же значение, что и *val но ничто не владеет val так что это будет утечка памяти. Вы, вероятно, хотели сделать это:

int * val = new int(5);
std::shared_ptr<int> myPtr(val);

или более вероятно это:

int val = 5;
std::shared_ptr<int> myPtr = std::make_shared<int>(val);
2

По вопросам рекламы [email protected]