2011-01-29 16 views
11

considerar lo siguiente:¿Es necesario definir constructores de movimiento de diferentes clases?

struct X 
{ 
    Y y_; 

    X(const Y & y) :y_(y) {}  
    X(Y && y) :y_(std::move(y)) {} 
}; 

Es necesario definir un constructor como el segundo con el fin de sacar el máximo provecho de la semántica movimiento? ¿O será cuidado automáticamente en las situaciones apropiadas?

+0

Un generador de movimiento u operador de asignación se genera implícitamente [en ciertas circunstancias] (http://stackoverflow.com/questions/4819936/why-no-default-move-assignment-move-constructor/4820339#4820339). Como ha declarado un constructor de copias aquí, también deberá declarar y definir un constructor de movimientos apropiado usted mismo. Sin embargo, puede eliminar ambos y tener el mismo comportamiento en su caso específico. –

+1

@James: información útil. Sin embargo, no definí un constructor de copia aquí. Definí un constructor de Y a X. –

+0

Oh. Lo siento, solo vi cartas y pensé que eran todas iguales. –

Respuesta

7

Sí, pero no. Su código sólo debe ser la siguiente:

struct X 
{ 
    Y y_; 

    X(Y y) : // either copy, move, or elide a Y 
    y_(std::move(y)) // and move it to the member 
    {} 
}; 

Si alguna vez se dice en el diseño "Necesito mi propia copia de estos datos" *, a continuación, sólo debe tomar el argumento de valor y moverlo a donde tiene que estar . No es su trabajo decidir cómo construir ese valor, eso depende de los constructores disponibles para ese valor, así que déjelo hacer esa elección, sea lo que sea, y trabaje con el resultado final.

* Esto se aplica a funciones también, por supuesto, por ejemplo:

void add_to_map(std::string x, int y) // either copy, move or elide a std::string 
{ 
    // and move it to where it needs to be 
    someMap.insert(std::make_pair(std::move(x), y)); 
} 

Nota que se aplica en C++ 03 también, en cierta medida, si era un tipo construible defecto y intercambiables (que todo se mueve de todos modos):

// C++03 
struct X 
{ 
    std::string y_; 

    X(std::string y) // either copy or elide a std::string 
    { 
     swap(y_, y); // and "move" it to the member 
    } 
}; 

Aunque esto no parece ser tan ampliamente hecho.

+0

Exactamente lo que estaba buscando, una forma de hacerlo en una función. Gracias GMan. –

1

Sí, es necesario. Un const ref solo puede ser una copia, no un movimiento.

Cuestiones relacionadas