Есть ли способ использовать shared_ptr <void> для shared_ptr <T>?

Я хочу сохранить умное поведение std::shared_ptr. Итак, есть способ применить общий указатель void к другому типу, не запутывая подсчет ссылок? Я не могу получить необработанный указатель и создать из него новый общий указатель.

Ответы

Ответ 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.