Простой вопрос здесь: разрешено ли вам явно удалить boost::shared_ptr
сам? Должны ли вы когда-нибудь?
Пояснение, я не имею в виду удалить указатель, удерживаемый shared_ptr
, Я имел в виду фактическое shared_ptr
сам. Я знаю, что большинство людей предлагают не делать этого, поэтому мне просто интересно, нормально ли это делать прямо.
Ваш вопрос не ясен. Если вы выделили 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.
delete
shared_ptr
если и только если он был создан с new
Так же, как и любой другой тип. Я не могу понять, почему вы создали shared_ptr
с new
, но ничто вас не останавливает.]
Хорошо ты мог записывать delete ptr.get();
,
Это почти неизбежно ведет к неопределенному поведению, когда Другой общие владельцы используют их shared_ptr
для доступа к удаленному объекту или последнему shared_ptr
объект уничтожается, и объект снова удаляется.
Так что нет, не стоит.
Цель shared_ptr
заключается в управлении объектом, который ни один «человек» не имеет права или обязанности удалять, потому что могут быть и другие, разделяющие право собственности. Так что тебе тоже не стоит этого хотеть.
Вы не можете принудительно установить счетчик ссылок на ноль, нет.
Подумайте, что потребуется для того, чтобы это работало. Вам нужно будет перейти в каждое место, где используется shared_ptr, и очистить его.
Если вы принудительно удалили общий указатель и установили его в NULL, он был бы как слабый_птр. Однако все те места в коде, которые используют этот shared_ptr, не готовы к этому и ожидают, что они содержат действительный указатель. У них нет оснований проверять NULL, и поэтому эти биты кода могут вылетать.
Если вы хотите смоделировать уменьшение количества, вы можете сделать это вручную в куче следующим образом:
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;
}
Но это не так полезно.
Явное удаление оказывается полезным в некоторых (очень?) Редких случаях.
В дополнение к явному удалению, иногда вы ДОЛЖНЫ явно уничтожать общий указатель, когда вы «удаляете» его!
Вещи могут стать странными при взаимодействии с кодом 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;
}