Me gusta la idea de las variables miembro de const, especialmente cuando envuelvo las funciones C en las clases. El constructor toma un identificador de recurso (por ejemplo, un descriptor de archivo) que permanece válido durante todo el tiempo de vida del objeto y el destructor finalmente lo cierra. (Esa es la idea detrás de RAII, ¿no?)Mover el constructor y las variables de miembros de la estructura
Pero con el C++ 0x move constructor me encuentro con un problema. Como el destructor también se invoca en el objeto "descargado", necesito evitar la limpieza del identificador del recurso. Dado que la variable miembro es const no tengo manera de asignar el valor -1 o INVALID_HANDLE (o valores equivalentes) para indicar al destructor que no debería hacer nada.
¿Hay alguna manera de que no se llame al destructor si el estado de un objeto se movió a otro objeto?
Ejemplo:
class File
{
public:
// Kind of "named constructor" or "static factory method"
static File open(const char *fileName, const char *modes)
{
FILE *handle = fopen(fileName, modes);
return File(handle);
}
private:
FILE * const handle;
public:
File(FILE *handle) : handle(handle)
{
}
~File()
{
fclose(handle);
}
File(File &&other) : handle(other.handle)
{
// The compiler should not call the destructor of the "other"
// object.
}
File(const File &other) = delete;
File &operator =(const File &other) = delete;
};
Tu respuesta es, con seguridad, un camino por recorrer. Pero relacionado con C++ 0x, no me gusta el estilo que tienen los destructores para comprobar si la destrucción realmente debería ocurrir. ¿No deberían suponer que el objeto está en pleno funcionamiento y ahora es el punto de destrucción? – mazatwork
@mazatwork: Bueno, piénsalo de esta manera. Supongamos que tiene un objeto complicado que podría estar en varios estados diferentes y cada uno requiere un conjunto diferente de destructores. Como, por ejemplo, hay un caché que puede inicializarse o no, o una conexión de base de datos que puede o no ser cerrada. ¿No estás 'realmente destruyendo' cuando no cierras la conexión de la base de datos que no está abierta en tu destructor? Por supuesto no. Esto es básicamente lo mismo. Todavía estás destruyendo, es solo que el estado en el que se encuentra el objeto no cumple con mucho trabajo. – Omnifarious
¿Por qué no dejar que el constructor de movimientos realice una limpieza (si es realmente necesario) para que el destructor quede con la destrucción real? En mi opinión, esto encajaría mucho mejor. Debido a que hablamos del mismo objeto, una doble destrucción podría no ser razonable. Tu ejemplo con objetos complejos es algo que trato de evitar usando técnicas como RAII y DI. – mazatwork