2012-07-02 2 views
12

Я пытался писать этот классСтранное поведение для unique_pointer в Visual Studio 2010

#include <memory> 

class ContainerUnique 
{ 
public: 

    ContainerUnique(void); 
    ~ContainerUnique(void); 

private: 
    std::unique_ptr<UniqueElement> u; 
}; 

Где UniqueElement является класс POD определяется в другом месте. Теперь я определяю тело конструктора следующим образом:

ContainerUnique::ContainerUnique(void) 
{ 
    auto tmp = new UniqueElement(1); 

    this->u(tmp); // u is a unique_ptr<UniqueElement>. Should this call compile? 
} 

И это соответствует без исключений. Запустив программу, я обнаружил, что после вызова конструктора ContainerUniqueu содержит нулевой указатель.

Является ли это предполагаемым поведением? И какой метод unique_ptr я действительно звоню?

+3

Не уверен в проблемах, с которыми вы сталкиваетесь. Но избегайте их, инициализируя переменную-член u в списке инициализации конструктора. –

+0

Да, это решение, которое я использовал в своем реальном коде, но я все еще не уверен в том, что происходит в этом примере. –

+0

Попробуйте напечатать тип вашей автоматической переменной. Не уверен, работает ли typeid. Как только вы знаете тип, остальное должно быть легко. –

ответ

19

This is a known problem with VS2010's unique_ptr.Он публично наследует от своего Deleter, если он пуст, как оптимизация (пустая база оптимизации). Недостатком публичного наследования является то, что все члены deleter также становятся доступными членами unique_ptr, в этом случае его operator()(T*), который удаляет указатель.

Ошибка исправлена ​​в библиотеке VS2012, где наследование изменено на личное.

+1

ах, ты избил меня. Хорошая находка. – stijn

2

Это должно быть сделано как

ContainerUnique::ContainerUnique(void):u(new UniqueElement(1)) { 
} 
+1

Так я решил проблему в своем производственном коде, но я все еще не уверен в том, что происходит в этом примере. –

8

Вы вызываете default_delete<UniqueElement>::operator() (UniqueElement* ptr), потому что uniqe_ptr извлекается из него (чтобы извлечь выгоду из пустой оптимизации базового класса), и он удаляет ptr. Для вас это не совсем точно, но я не думаю, что стандарт запрещает это.

Смежные вопросы