Primero: ¿dónde están definidos std::move
y std::forward
? Sé lo que hacen, pero no puedo encontrar pruebas de que se requiera un encabezado estándar para incluirlos. En gcc44 a veces std::move
está disponible, y algunas veces no, por lo que una directiva de inclusión definitiva sería útil.Algunas aclaraciones sobre las referencias rvalue
Al implementar la semántica de movimiento, la fuente se deja presumiblemente en un estado indefinido. ¿Debería este estado necesariamente ser un estado válido para el objeto? Obviamente, debe poder invocar el destructor del objeto y asignarlo por cualquier medio que exponga la clase. Pero, si otras operaciones fueran válidas? Supongo que lo que estoy preguntando es, si su clase garantiza ciertas invariantes, ¿debería esforzarse por imponer esas invariantes cuando el usuario ha dicho que ya no se preocupan por ellas?
Siguiente: cuando no le importa la semántica de movimiento, ¿hay alguna limitación que haga que una referencia no constante sea preferible a una referencia rvalue cuando se trata de parámetros de función? void function(T&);
sobre void function(T&&);
Desde la perspectiva de una persona que llama, ser capaz de pasar funciones con valores temporales ocasionalmente es útil, por lo que parece que se debe otorgar esa opción siempre que sea factible hacerlo. Y las referencias rvalue son en sí mismas lvalues, por lo que no se puede inadvertidamente llamar a un constructor de movimiento en lugar de un constructor de copia, o algo así. No veo un inconveniente, pero estoy seguro de que hay uno.
Lo que me lleva a mi última pregunta. Aún no puede vincular temporalmente a referencias no const. Pero puede vincularlos a referencias de valores no const. Y luego puede pasar esa referencia como referencia no constante en otra función.
void function1(int& r) { r++; }
void function2(int&& r) { function1(r); }
int main() {
function1(5); //bad
function2(5); //good
}
Además de que no hace nada, ¿hay algún problema con ese código? Mi instinto dice, por supuesto, que no, ya que cambiar las referencias de valores es una especie de punto de su existencia. Y si el valor pasado es legítimamente const, el compilador lo atrapará y le gritará. Pero, por lo que parece, este es un rodeo de un mecanismo que presumiblemente se puso en marcha por una razón, así que solo me gustaría la confirmación de que no estoy haciendo nada tonto.
Gracias por la respuesta elaborada. Creo que entiendo las cosas menos que antes, pero no por tu culpa. Según ese artículo, una función como 'void f (int &&);' no puede aceptar lvalues a menos que se emitan explícitamente. Definitivamente ese no es el comportamiento que he estado viendo, así que supongo que esto es una deficiencia en gcc-4.4 's. Implementación. Lo que hace que todas las pruebas que he estado haciendo entiendan cómo todo interactúa bastante inútil: -/ –
@Dennis, sí, eso fue cambiado en el borrador de trabajo hace un tiempo: 'int &&' no se une implícitamente a lvalues más. Es demasiado peligroso. –
El enlace 'este artículo' está muerto. ¿Puedes cambiarlo por uno actual? –