2011-08-04 10 views
10

Si muevo-construye a desde b, ¿sigue siendo necesario para destruir b, o puedo escapar sin hacerlo?¿Se movieron de los objetos necesarios para ser destruidos?

Esta pregunta pasado por la cabeza durante la ejecución de una plantilla optional<T>. Extracto:

~optional() 
{ 
    if (initialized) 
    { 
     reinterpret_cast<T*>(data)->~T(); 
    } 
} 

optional(optional&& o) : initialized(o.initialized) 
{ 
    if (initialized) 
    { 
     new(data) T(std::move(*o)); // move from o.data 
     o.initialized = false;  // o.data won't be destructed anymore! 
    } 
} 

Por supuesto, sólo podría reemplazar al bool initialized con una enumeración trivaluada que distingue entre inicializado, no inicializado y se trasladó -desde. Solo quiero saber si esto es estrictamente necesario.

+0

¿Por qué usar destructor? ¿por qué no eliminar? después de mudarse, puede establecerlo en 0. – balki

+2

@balki: No estoy seguro de lo que está obteniendo. No hay memoria dinámica en mi plantilla 'opcional ', así que no hay nada que 'borrar'. – fredoverflow

+1

¡Estaba implementando exactamente lo mismo y tenía exactamente la misma pregunta! ¡Gracias! – VF1

Respuesta

15

Sí, todavía es necesario para destruir b. Un objeto movido es un objeto válido y construido. En algunos casos, incluso puede contener recursos que aún deben eliminarse. En el código genérico tal como se muestra, T puede que ni siquiera tenga un constructor de movimiento. En este caso, puede invocar un constructor de copia. Entonces definitivamente no puedes asumir que ~ T() es un no-operativo y puede eludirse.

+0

+1 que tiene perfecto sentido – fredoverflow

+2

+1, no me di cuenta de que podría llamar a la parte del constructor de copias. – Puppy

4

Sí, usted todavía tiene que destruir ellos. Uno de los diseños que puede mostrar este defecto es, por ejemplo, patrones basados ​​en observadores donde un objeto mantiene listas de punteros a otro. No ejecutar el destructor no eliminará el puntero y el código se bloqueará cuando intente acceder a un objeto que ya no existe.

La cosa más fácil de hacer en su ejemplo es sólo para inicializar No Configurado en false en el pasado -desde objeto. El valor todavía está definido para estar en un estado válido después de ser movido desde, y el destructor del valor r al que se refiere lo limpiaría sin más intervención.

2

me gustaría responder 'No' a su pregunta, pero no estoy seguro de que es incluso la pregunta correcta. Considere lo siguiente:

{ // start of scope 
    T maybe_moved; 
    if(some_condition) { 
     T(std::move(maybe_moved)); 
    } 
// end of scope 
} 

T::~T(), obviamente, debe ser llamado una sola vez para el objeto maybe_moved. Si un constructor de movimientos lo llamara, ¿cómo haría que ese código tan inocuo funcione?

+0

Mi constructor de movimientos no llama a ningún destructor ...? – fredoverflow

+0

@FredOverflow Presumiblemente, cualquiera que sea el mecanismo hipotético destruido movido-de los objetos en su pregunta se aplica. –

+0

La pregunta de @Barry OP se refiere a miembros especiales definidos por el usuario, no a cómo se especifica el idioma. Como ya presenté mi respuesta, ¿cómo puede el * move constructor * realizar este deber (es decir, desde dentro de la declaración if, en este caso). –

Cuestiones relacionadas