Contrariamente a la opinión popular, no hay garantía de que el asignar el resultado de una función que devuelve un objeto de valor a una referencia constante se traducirá en un menor número de copias de asignar al objeto sí mismo.
Cuando asigna un valor de referencia a una referencia constante, el compilador puede enlazar la referencia de dos formas. Puede crear un nuevo temporal al copiar el valor r y enlazar la referencia a eso, o puede enlazar la referencia directamente con el valor r mismo.
Si el compilador no puede hacer la optimización 'obvia' para eliminar el temporal y elide el constructor de copia para el valor de retorno de getFoo
, entonces ¿qué tan probable es que sea capaz de hacer la forma más eficiente de vincular una rvalue a una referencia constante sin hacer un nuevo temporal?
Una razón para usar una referencia de referencia sería hacer que la función sea más robusta frente a posibles cortes.Si el tipo de retorno fuera en realidad un tipo derivado de Foo
, la asignación a una referencia de clase de clase base estaría garantizada para no cortar, incluso si el compilador creó un objeto temporal a partir del valor r devuelto por la función. El compilador también generará la llamada correcta al destructor de clase derivado independientemente de si el destructor en la clase base es virtual o no. Esto se debe a que el tipo de objeto temporal creado se basa en el tipo de expresión que se está asignando y no en el tipo de la referencia que se está inicializando.
nota que se hizo la cuestión de cómo muchas copias del valor de retorno es totalmente independiente de la optimización valor de retorno y la optimización valor de retorno llamado. Estas optimizaciones se refieren a eliminar la copia del resultado rvalue de evaluar una expresión de retorno o de una variable local con nombre en el valor de retorno de una función en el cuerpo de la función en sí. Obviamente, en el mejor de los casos posibles, se puede realizar una optimización del valor de retorno y se puede eliminar el valor de retorno temporal para que no se realice ninguna copia en el objeto devuelto.
Si el compilador vincula un valor r para const referencia haciendo una copia, que puede implicar un constructor de copia, que está definido por A :: A (const A &), ¿cómo compilaría el siguiente código? A x = A (param); –
@ZheYang: a partir de una nota en el antiguo estándar: "Claramente, si la inicialización de referencia que se procesa es una para el primer argumento de una llamada de constructor de copia, una implementación debe elegir la primera alternativa (vincular sin copiar) para evitar la recursión infinita ". En el nuevo estándar, esta opción se ha eliminado de las implementaciones. –
Interesante. Creo que es solo porque en el nuevo estándar ahora tenemos el constructor de movimientos, pero de todos modos puede faltar. –