2010-06-03 20 views
5

La pregunta original está relacionada con la sobrecarga del operador = y me gusta compartir mis hallazgos, ya que no fue trivial para mí encontrarlos. No me puedo imaginar un ejemplo razonable para usar (a = b) como lvalue. Con la ayuda de IRC y google he encontrado el siguiente artículo: http://msdn.microsoft.com/en-us/magazine/cc301415.aspxPor qué el operador = devuelve la referencia no const referencia

proporciona dos ejemplos.

(a=b)=c 

    f(T&); 
    f(a=b) 

pero ambos no son buenos, y creo que es una mala práctica. El segundo me da la misma sensación. ¿Podría proporcionar más buenos ejemplos de por qué no debería ser constante?

Respuesta

11

Una buena razón es que uno de los requisitos de la norma para una clase X para ser utilizable en los contenedores estándar es que la expresión a = b debe tener un tipo X& (donde a es un valor-I de tipo X y b es un rvalue del tipo X).

+0

Buena captura, compañero :) –

+0

¡Gracias! Buen tiro. Voy a votar esto. (Pero probablemente esto esté relacionado con las malas prácticas en STL. ¿Puedes dar un ejemplo puro de C++?) – outmind

+2

¿Pero por qué el contenedor necesita un 'X &' como retorno? – kennytm

2

He pasado algún tiempo y aquí es mi ejemplo:

class A 
{ 
public: 
    const A& operator= (const A& a) {return *this;} 
}; 

int main(int argc, char* argv[]) 
{ 
    A a1; 
    A& a2 = a1; 
    A& a3 = (a2 = a1); 
} 

y la salida del compilador: : error C2440: 'inicialización': no ​​se puede convertir de 'const A' a 'A &'

Lo he comprobado en MS VS 2010, ¿pero es cierto en otras plataformas? Y si este ejemplo es condición suficiente para = ser no const?

+1

También compila el error en g ++. – kennytm

+0

¡Gracias! ¿Cuáles son sus ideas sobre la suficiencia? – outmind

1

¿Por qué debería ser const? Si lo asignas, obviamente es modificable. Eso sería artísticamente limitante.

En cuanto a los casos de uso, por qué no:

T &local = t1 = t2 = t3; 

En este ejemplo, local no es const.

+0

¿Qué tipos de t1, t2, t3? T * o T o T &? – outmind

+1

¿Por qué se puede asignar a un puntero? – kennytm

+0

@outmind: en este caso, t3 es un tipo que es convertible y/o asignable a t2, t2 es un tipo que es convertible y/o asignable a t1, y t1 es un tipo que es convertible y/o asignable a T *. – Bill

0

Si consideramos tres auto_ptr A, B y C, el operador = tiene que devolver una referencia no constante por lo que se puede hacer varios cesionarios ya asignar el puntero a otro modifica la primera.

así que si tenemos a = b = c, ocurre lo siguiente: c se asigna a b (c se modifica para apuntar a NULL), el operador devuelve una referencia a b la referencia devuelto por (b = c) se asigna a a, por lo tanto, se modifica para apuntar a nulo, lo cual solo es posible si la referencia es no const.

8

Probablemente porque así es como funcionan los tipos nativos del idioma. ej .:

int x = 0, y = 1, z = 2; 
(x = y) = z; 

yo sepa, el Dr. BS dijo que es una buena cosa a tener consistencia en el lenguaje. es decir, los tipos definidos por el usuario deben comportarse exactamente como los tipos nativos.

+0

Gracias! Buen ejemplo. C compatibilidad con versiones anteriores y consistencia. – outmind

+2

Excepto que el comportamiento de C++ es de hecho diferente de C. Del estándar C99 (6.5.16/3 "Operadores de asignación"): "Una expresión de asignación tiene el valor del operando izquierdo después de la asignación, pero no es un valor l. " Sería interesante saber qué pensaba Stroustrup sobre por qué este cambio era necesario.No puedo pensar fácilmente en un buen caso de uso deseable (pero eso solo significa que alguien tiene que decirme o recordarme qué es). –

+0

¿Coherencia con qué? En lenguaje C, el resultado de la asignación es un valor r. C++ es * no * consistente con C en ese sentido. – AnT

2

Andrew Koenig ha escrito un post sobre esto hace mucho tiempo. Mucho de esto se reduce a hacer lo que la gente espera en circunstancias poco comunes. El ejemplo que da es que en C, return x=y; siempre significa lo mismo que x=y; return x;.En C++, si devuelve esencialmente cualquier cosa otra que una referencia (incluida una referencia const), las dos pueden significar cosas diferentes.

Editar: Lo siento, he vinculado a la publicación incorrecta. Pruebe this one. El problema surge del hecho de que un T const & puede vincularse a un objeto temporal en lugar de a un objeto "real", por lo que lo que sucedió con el código anterior fue que creó un temporal, copió el objeto en él, enlazó la referencia al mismo, destruyó el objeto temporal, luego devolvió la referencia (ahora colgando).

+1

¿Cómo? ¿Cómo pueden significar cosas diferentes si devuelves algo que no sea referencia? – AnT

Cuestiones relacionadas