2012-07-02 6 views
12

he intentado escribir esta clasecomportamiento extraño para unique_pointer en Visual Studio 2010

#include <memory> 

class ContainerUnique 
{ 
public: 

    ContainerUnique(void); 
    ~ContainerUnique(void); 

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

Dónde UniqueElement es una clase POD define en otra parte. Ahora defino el cuerpo constructor así:

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

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

Y cumple sin excepciones. Ejecutando el programa encuentro que después de que se ha llamado al constructor de ContainerUnique, u contiene un puntero nulo.

¿Es este el comportamiento previsto? ¿Y qué método unique_ptr estoy llamando?

+3

No estoy seguro de los problemas que está teniendo. Pero evítelos inicializando la variable miembro u en la lista de inicio del desarrollador. –

+0

Sí, esa es la solución que utilicé en mi código real, pero todavía no estoy seguro de lo que está sucediendo en el ejemplo. –

+0

Intente imprimir el tipo de su variable automática. No estoy seguro de si typeid funciona. Una vez que sepa el tipo, el resto debería ser fácil. –

Respuesta

19

This is a known problem with VS2010's unique_ptr. Se públicamente hereda de su Deleter si está vacío como una optimización (optimización de base de vacío). La desventaja de la herencia pública es que todos los miembros del eliminador también se vuelven miembros disponibles de unique_ptr, en este caso es operator()(T*) que elimina el puntero.

El error se corrigió en la biblioteca de VS2012 donde la herencia se cambió a privada.

+1

ah, me ganaste. Buen descubrimiento. – stijn

2

debe hacerse como

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

Esta es la forma en que resolví el problema en mi código de producción, pero todavía no estoy seguro de lo que está sucediendo en el ejemplo. –

8

Está llamando al default_delete<UniqueElement>::operator() (UniqueElement* ptr), porque uniqe_ptr deriva de él (para beneficiarse de la optimización de la clase base vacía), y borra ptr. No es exactamente el comportamiento previsto para ti, aunque no creo que el estándar lo prohíba.