2012-06-28 26 views
18

A menudo se dice que en C++ 11 es sensato devolver std::vector por valor.Regreso std :: vector por valor

En C++ 03 esto era muy cierto ya que RVO debería optimizar la copia. Pero ese debería atemorizar a la mayoría de los desarrolladores.

  • En C++ 11 siempre se moverá una variable local devuelta std::vector?
  • ¿Qué pasa si ese vector es miembro de una variable local en lugar de una variable local en sí?
  • Obviamente, no se moverá una variable global. ¿Qué otros casos no se moverá?
+0

Ver también [esta pregunta] (http://stackoverflow.com/q/9532608/500104). – Xeo

Respuesta

15

En primer lugar, cada vez que se puede eliminar una copia anteriormente, aún puede elase ahora, y los movimientos se pueden elidir en las mismas situaciones. Para el resto de esta publicación, asumiré que la elisión no ocurre por alguna razón (pretenden que el escritor del compilador fue flojo de mala manera).

En C++ 11 siempre se moverá una variable local devuelta std :: vector?

Cada vez que se cumplen los criterios para la elisión de copia, o la variable es explícitamente std::move d.

¿Qué pasa si ese vector es miembro de una variable local en lugar de una variable local?

No se moverá a menos que explícitamente std::move d.

Obviamente no se moverá una variable global. ¿Qué otros casos no se moverá?

Cada vez que no se cumplen los criterios para la elisión de copia y la variable no es explícitamente std::move d.

Ninguno de estos es una razón válida para no devolver por valor. La devolución por valor está bien, porque incluso cuando el valor no se mueva automáticamente, puede forzarlo con std::move.

+0

No creo que se moverá si puede RVO'd. – juanchopanza

+0

@juanchopanza, bueno, sí, ninguno de estos previene las optimizaciones. –

+0

OK; su primer punto parece implicar que ** se ** moverá cada vez que se cumplan los criterios de elisión de copia. – juanchopanza

8

En C++ 11 siempre se moverá una variable local std::vector?

Para una variable local, incluso un parámetro por valor, el compilador tiene que siempre intento para moverlo primero (si ni el movimiento ni la copia se pueden elided por cualquier razón, incluso si los criterios son reunió). Si eso no funciona, trata de nuevo con una copia:

§12.8 [class.copy] p32

Cuando se cumplen los criterios para la elisión de una operación de copia o se cumplirían, salvo por el hecho de que el objeto de origen es un parámetro de función, y el objeto que se va a copiar se designa con un lvalue, la resolución de sobrecarga para seleccionar el constructor para la copia se realiza primero como si el objeto se designara con un valor r.Si la resolución de sobrecarga falla, o si el tipo del primer parámetro del constructor seleccionado no es una referencia rvalue al tipo del objeto (posiblemente cv-qualified), la resolución de sobrecarga se realiza nuevamente, considerando el objeto como un valor l. [Nota: Esta resolución de sobrecarga de dos etapas debe realizarse independientemente de si se producirá elisión de copia. Determina el nombre del constructor que se invocará si no se realiza una elisión, y el constructor seleccionado debe estar accesible incluso si se elimina la llamada. -finalizacion]

¿Qué pasa si ese vector es un miembro de una variable local en lugar de una variable local?

No se intentará mover un subobjeto, ya que no cumple los criterios de elisión de copia. (Que es mudo, en mi humilde opinión, pero eso es lo que actualmente es. No creo que los dos deben estar vinculados, ya que un subobjeto perfectamente bien se puede mover si es local.)

Obviamente el retorno de una variable global no ser movido ¿Qué otros casos no se moverá?

Una referencia obviamente no se moverá. Aparte de eso, realmente no puedo pensar en otra cosa.

+0

¿Qué tal una referencia a un local? ¿Qué ocurre si se llama a 'std :: move' en la referencia local? –

+0

@deft_code: una referencia en sí misma no se moverá automáticamente, parece que mi última oración no fue lo suficientemente clara al respecto. Una referencia 'std :: move''d moverá el objeto referido. – Xeo

Cuestiones relacionadas