Я хочу сохранить умное поведение std::shared_ptr
. Итак, есть способ применить общий указатель void к другому типу, не запутывая подсчет ссылок? Я не могу получить необработанный указатель и создать из него новый общий указатель.
Есть ли способ использовать shared_ptr <void> для shared_ptr <T>?
Ответ 1
Вы можете использовать броски указателей из rob mayoff answer; но будь осторожен. Легко непреднамеренно вызвать поведение undefined здесь:
struct MyClass {};
void* rawPtr = new MyClass;
shared_ptr<void> exampleVoid(rawPtr); // Undefined behavior;
// calls delete (void*)ptr;
shared_ptr<void> exampleVoidCons(new MyClass);
// OK, calls shared_ptr<void>::shared_ptr<MyClass>(MyClass*) which
// makes a deleter calling delete (MyClass*)ptr;
shared_ptr<MyClass> example(new MyClass); // OK, calls delete (MyClass*)ptr;
shared_ptr<void> castToVoid = static_pointer_cast<void>(example);
// OK, shared_ptr deleter is erased so this still calls delete (MyClass*)ptr;
Обычно это поведение undefined приведет к тому, что деструктор типа не будет вызван. Например, см. Вывод на ideone и обратите внимание, что версия, помещенная в void*
, никогда не печатает, что она была уничтожена.
См. С++ 11 5.3.5 [expr.delete]/3:
В первом альтернативе (удалить объект), если статический тип подлежащего удалению объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа объекта, подлежащего удалению, и статическим тип должен иметь виртуальный деструктор или поведение undefined.
Поскольку у фактического объекта никогда не будет динамического типа void
, а void
никогда не будет базовым классом динамического типа, delete
ing void*
запускает поведение undefined.
Ответ 2
Вы можете использовать std::static_pointer_cast
или std::dynamic_pointer_cast
в зависимости от того, какой тип вы хотите.