Pregunta

Por favor, tenga en cuenta las tres funciones.

std::string get_a_string()
{
    return "hello";
}

std::string get_a_string1()
{
    return std::string("hello");
}

std::string get_a_string2()
{
    std::string str("hello");
    return str;
}
  1. Will RVO se aplicará en todos los tres casos?
  2. ¿Está bien para devolver un temporal, como en el código anterior? Creo que está bien, ya que voy a volver por valor en lugar de devolver cualquier referencia a él.

¿Alguna idea?

¿Fue útil?

Solución

En los dos primeros casos RVO optimización se llevará a cabo. RVO es característica de edad y la mayoría de los compiladores lo soporta. El último caso se llama así NRVO (RVO Named). Eso es relativamente nueva característica de C ++. Norma permite, pero no requiere la aplicación de NRVO (así como RVO), pero algunos compiladores lo soporta.

Se puede leer más sobre RVO en el artículo 20 del libro de Scott Meyers más eficaz C ++. 35 nuevas formas de mejorar los programas y diseños .

Aquí es un artículo bueno de NRVO en Visual C ++ 2005.

Otros consejos

En primer lugar, es completamente aceptable para devolver un valor temporal que es lo que haces. Se copia y aunque el original irá fuera del ámbito de la copia no lo hará y puede ser utilizado con seguridad por la persona que llama.

En segundo lugar, los tres casos son de hecho idénticos (ya que no accede a la temporal en el tercer caso de todos modos) y un compilador que incluso podría emitir el mismo código para todos ellos. Por lo tanto puede utilizar RVO en los tres casos. Esto es totalmente dependiente del compilador.

Todos los casos son correctos. Todos ellos construirán un temporal y aplicar el constructor de copia del tipo de retorno. Necesariamente, si no hay un constructor de copia, el código fallará.

RVO sucederá en los tres casos en la mayoría de los compiladores. La única diferencia es el último en que la norma no lo fuerce. Esto debido a que tiene una variable llamada. Pero la mayoría de los compiladores son lo suficientemente inteligentes como para aplicar a RVO todavía ... la tarde la variable llamada se declara y los menos transformaciones que se aplica a, las mejores probabilidades para RVO a ser aplicado a una variable llamada.

Por cierto, volviendo una referencia es por supuesto posible, ya que se puede haber visto en otro código. Lo que no debe hacer es devolver una referencia t un objeto local.

std::string& get_a_string2()
{
    std::string str("hello");
    return str; //error!
}

producirá un error de tiempo de compilación, como usted sabe. Sin embargo,

std::string& get_a_string2(std::string& str)
{
    // do something to str
    return str; //OK
}

funcionará bien. En este caso, no hay construcción de la construcción o la copia en cuestión. Simplemente la función devuelve una referencia a su argumento.

  1. Depende de su compilador - qué plataforma se está refiriendo? La mejor manera de averiguarlo es para compilar un muy pequeña aplicación de prueba y comprobar la ASM su compilador produce.

  2. Sí, está bien, aunque nunca se menciona lo que le preocupa; ¿velocidad? ¿estilo? puede un local temporal a una referencia constante - la vida útil del temporal se extenderá a toda la vida útil de la referencia - probarlo y ver por sí mismo! (Herb Sutter exaplins esta aquí ) Véase final del post, por ejemplo.

OMI ya está casi siempre mejor confiar en su compilador para optimizar el código para usted. Hay muy pocos casos en el que tiene que preocuparse por este tipo de cosas (código de nivel muy bajo es una de esas áreas, donde usted interactivo con los registros de hardware).

int foo() { return 42; }

int main(int, char**)
{
    const int &iRef = foo();
    // iRef is valid at this point too!
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top