valores valor tipos salida retornan referencias referencia que punteros por paso parametros parametro operadores funciones entrada c++ reference const-reference return-by-reference return-by-value

tipos - C++ Valor de retorno, referencia, referencia constante



que es un parametro en c++ (5)

¿Puede explicarme la diferencia entre devolver el valor, referencia al valor y const referencia al valor?

Valor:

Vector2D operator += (const Vector2D& vector) { this->x += vector.x; this->y += vector.y; return *this; }

Referencia no-const:

Vector2D& operator += (const Vector2D& vector) { this->x += vector.x; this->y += vector.y; return *this; }

Referencia de Const:

const Vector2D& operator += (const Vector2D& vector) { this->x += vector.x; this->y += vector.y; return *this; }

¿Cuál es el beneficio de esto? Entiendo que el sentido detrás del paso de referencia constante funcione, ya que quiere asegurarse de no modificar este valor al que apunta la referencia dentro de la función. Pero estoy confundido por el significado de devolver la referencia const. ¿Por qué la devolución de la referencia es mejor que la devolución del valor, y por qué el retorno de la referencia const es mejor que el retorno de la referencia no const?


Como se señaló, pero luk32 es solo para garantizar que no se permiten cambios a los objetos devueltos por esta función. Esto básicamente puede ayudarte a encontrar tus errores lógicos en tiempo de compilación. Supongamos que está seguro de no cambiar un objeto, y su código está cambiando el objeto, se puede rastrear. Se puede pensar en una buena práctica de codificación.


Es exactamente lo mismo que pasar argumentos a la función.

Desea devolver una referencia const cuando devuelve una propiedad de un objeto, que no desea modificar fuera de ella. Por ejemplo: cuando su objeto tiene un nombre, puede hacer el siguiente método const std::string& get_name(){ return name; }; const std::string& get_name(){ return name; }; . Cuál es la forma más óptima. Permites un acceso de "solo lectura" a una propiedad interna, sin copia de retorno.

Cuando está sobrecargando operadores, se espera que devuelva un objeto que sea mutable, de lo contrario, cierta sintaxis que normalmente se espera que funcione generará errores. Es bastante importante cuando intentas un encadenamiento extraño.

Por ejemplo, la opción 3 no funcionará con algo como (v1 += v2).non_const_method() , mientras que lo siguiente sería:

v1+=v2; v1.non_const_method();


La diferencia entre return-by-value y return-by-reference tiene efecto durante el tiempo de ejecución:

Cuando devuelve un objeto por valor, se llama al constructor de copia y se crea una instancia temporal en la pila.

Cuando devuelve un objeto por referencia, todo lo anterior no tiene lugar, lo que mejora el rendimiento.

La diferencia entre retorno por referencia y retorno por referencia constante no tiene efecto de tiempo de ejecución, y está simplemente ahí para protegerlo de escribir código erróneo.

Por ejemplo, con Vector2D& operator += (const Vector2D& vector) , puede hacer:

(x+=y)++ o (x+=y).func() donde func es una func no const en la clase Vector2D .

Pero con const Vector2D& operator += (const Vector2D& vector) , el compilador generará un error por cualquier intento similar.


No hay diferencia a menos que escribas algo raro como

(v1 += v2) = v3;

En el primer caso, la asignación será a un temporal, y el efecto general será v1 += v2 .

En el segundo caso, la asignación será a v1 , por lo que el efecto general será v1 = v3 .

En el tercer caso, la asignación no será permitida. Esta es probablemente la mejor opción, ya que tal rareza es casi seguro un error.

¿Por qué devolver la referencia es mejor que devolver el valor?

Es potencialmente más eficiente: no tienes que hacer una copia del objeto.

y por qué el regreso de la referencia de const es mejor que el de la referencia de no-const?

Previene la rareza como en el ejemplo anterior, al tiempo que permite un encadenamiento menos extraño, como

v1 = (v2 += v3);

Pero, como se señala en los comentarios, significa que su tipo no admite las mismas formas de uso (ab) que los tipos incorporados, que algunas personas consideran deseable.


Valor:

Devolver por valor significa que está devolviendo una copia de un objeto. Esto impone requisitos a la clase (debe ser copiable o movible). Esto significa que para el objeto de algunas clases, devolver por valor puede ser costoso (en el caso de que RVO o NRVO no funcionen o estén apagados). Esto también significa que el nuevo objeto es independiente (sujeto a su diseño) de otros objetos y es un valor propio. Esto es lo que probablemente debería devolver de muchos operadores binarios como +, -, * y así sucesivamente.

Referencia no const:

Realmente devuelves un alias para otro objeto. El alias que no es const le permite modificar el objeto alias. Esto es lo que debe devolver de algunos opradores unarios como el prefijo ++ y -, y * (desreferencia), ya que generalmente quiere tener la capacidad de modificar el objeto devuelto.

Esto es devuelto por el operador >> y el operador << sobrecargado para transmisiones. Esto permite el encadenamiento de operadores:

cout << 5 << "is greater then" << 1 << endl; cin >> myInt >> myFloat;

También puede devolver la referencia a * esto cuando desee permitir el encadenamiento de métodos regulares como este:

object.run().printLastRunStatistics();

Referencia de Const:

Como arriba, pero NO PUEDE modificar el objeto alias. Se puede usar en lugar de devolver por valor cuando el objeto a devolver es costoso de copiar y cuando puede garantizar su existencia después de regresar de una función.

Esto es lo que el operador = generalmente devuelve para permitir asignaciones múltiples de una manera en que los tipos estándar los soportan:

a = b = c;

Const-reference utilizada en operator = impide este tipo de uso (no es compatible con el tipo estándar por lo que recuerdo):

++(a = b);

lo cual estaría permitido si se usara una referencia normal.