Явное удаление shared_ptr

Простой вопрос здесь: разрешено ли вам явно удалить boost::shared_ptr сам? Должны ли вы когда-нибудь?

Пояснение, я не имею в виду удалить указатель, удерживаемый shared_ptr, Я имел в виду фактическое shared_ptr сам. Я знаю, что большинство людей предлагают не делать этого, поэтому мне просто интересно, нормально ли это делать прямо.

17

Решение

Ваш вопрос не ясен. Если вы выделили shared_ptr динамически, то вам, безусловно, разрешено delete это когда хочешь.

Но если вы спрашиваете, разрешено ли вам удалять объект, которым управляет shared_ptrтогда ответ … это зависит. Если shared_ptr::unique возвращает true, затем вызывает shared_ptr::reset удалит управляемый объект. Однако если shared_ptr::unique возвращает false, это означает, что существует более одного shared_ptrразделение прав собственности на этот объект. В этом случае вызов reset приведет только к уменьшению количества ссылок на 1, фактическое удаление объекта произойдет, когда последний shared_ptr управление этим объектом либо выходит из области видимости, либо само по себе reset,

РЕДАКТИРОВАТЬ:
После вашего редактирования кажется, что вы спрашиваете об удалении динамически выделенного shared_ptr, Что-то вроде этого:

auto sp = new boost::shared_ptr<int>( new int(42) );

// do something with sp

delete sp;

Это разрешено и будет работать как положено, хотя это будет необычный вариант использования. Единственное предостережение заключается в том, что если между распределением и удалением sp ты создаешь другой shared_ptr что разделяет право собственности на объект, удаляя sp не приведет к удалению объекта, это произойдет только тогда, когда счетчик ссылок для объекта станет равным 0.

25

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

[Изменить: вы можете delete shared_ptr если и только если он был создан с newТак же, как и любой другой тип. Я не могу понять, почему вы создали shared_ptr с new, но ничто вас не останавливает.]

Хорошо ты мог записывать delete ptr.get();,

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

Так что нет, не стоит.

Цель shared_ptr заключается в управлении объектом, который ни один «человек» не имеет права или обязанности удалять, потому что могут быть и другие, разделяющие право собственности. Так что тебе тоже не стоит этого хотеть.

5

Вы не можете принудительно установить счетчик ссылок на ноль, нет.

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

Если вы принудительно удалили общий указатель и установили его в NULL, он был бы как слабый_птр. Однако все те места в коде, которые используют этот shared_ptr, не готовы к этому и ожидают, что они содержат действительный указатель. У них нет оснований проверять NULL, и поэтому эти биты кода могут вылетать.

2

Если вы хотите смоделировать уменьшение количества, вы можете сделать это вручную в куче следующим образом:

int main(void) {
std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test")));
std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp);
delete sp;

std::cout << *(*sp2) << std::endl;    // test
return 0;
}

Или в стеке, используя std::shared_ptr::reset() вот так:

int main(void) {
std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test"));
std::shared_ptr<std::string> p2 = p;
p.reset();

std::cout << *p2 << std::endl;    // test
return 0;
}

Но это не так полезно.

1

Явное удаление оказывается полезным в некоторых (очень?) Редких случаях.

В дополнение к явному удалению, иногда вы ДОЛЖНЫ явно уничтожать общий указатель, когда вы «удаляете» его!

Вещи могут стать странными при взаимодействии с кодом C, передавая shared_ptr в качестве непрозрачного значения.

Например, у меня есть следующее для передачи объектов на язык сценариев Lua и из него, написанный на C. (www.lua.org)

static void push( lua_State *L, std::shared_ptr<T> sp )
{
if( sp == nullptr ) {
lua_pushnil( L );
return;
}

// This is basically malloc from C++ point of view.
void *ud = lua_newuserdata( L, sizeof(std::shared_ptr<T>));

// Copy constructor, bumps ref count.
new(ud) std::shared_ptr<T>( sp );

luaL_setmetatable( L, B::class_name );
}

Так что это shared_ptr в некоторой памяти malloc’d. Обратное заключается в следующем … (установка вызывается непосредственно перед тем, как Lua мусор соберет объект и освободит его).

static int destroy( lua_State *L )
{
// Grab opaque pointer
void* ud = luaL_checkudata( L, 1, B::class_name );

std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud);

// Explicitly called, as this was 'placement new'd
// Decrements the ref count
sp->~shared_ptr();

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