tenemos:¿Por qué está bien f (x) .swap (v) pero v.swap (f (x)) no?
vector<int> f(int);
vector<int> v;
Esto funciona:
f(x).swap(v);
Esto no es así:
v.swap(f(x));
Y por qué?
tenemos:¿Por qué está bien f (x) .swap (v) pero v.swap (f (x)) no?
vector<int> f(int);
vector<int> v;
Esto funciona:
f(x).swap(v);
Esto no es así:
v.swap(f(x));
Y por qué?
swap()
toma una referencia no const a un vector<int>
. Una referencia no const no puede vincularse a un valor r (un objeto temporal). Una llamada a una función que devuelve por valor (como f
) es un valor r.
La razón de que f(x).swap(v)
funciona es porque dentro de std::vector<int>::swap
, el objeto temporal devuelto por f(x)
puede utilizar this
para referirse a sí mismo. this
no es un valor r.
Puede llamar a funciones miembro en temporarios, pero en C++ no pueden vincularse a referencias no constantes.
Por ejemplo:.
int &x = 5; // illegal because temporary int(5) cannot be bound to non-const reference x
En este caso, está claro que no puede unir 'x' al resultado de la evaluación de' 5', porque la evaluación de '5' arroja el valor 5 de tipo' int', por lo que no tendría ningún objeto de tipo 'int' para enlazar. IOW, aquí hay ** no temporal ** 'int (5)'. – curiousguy
@ curiousguy: ¿Lo mismo de nuevo? No crea un temporal? ¿Por qué 'int const & x = 5' funciona? – Nawaz
@Nawaz funciona porque se crea un temporal. – curiousguy
En realidad, (mientras James' answer está en lo cierto (y también lo es Prasoon's), hay algún problema subyacente de captar
Cuando reducimos f(x)
a su resultado y
, y y.swap(v)
(o v.swap(y)
, no importa en este caso) para usar nombres de identificador generalizados, se convierte en
y.func(v)
Ahora, func()
ser una función miembro con un argumento, que en realidad tiene dos argumentos: lo que se ha pasado como v
y lo implícito this
puntero cada función miembro no estática recibe, aquí cota a y
. Al echar a un lado la encapsulación, cada función miembro llamada como y.func(v)
podría convertirse en una función no miembro para llamarse como func(y,v)
. (Y de hecho, en realidad hay funciones no miembro swap()
. Además, cada vez que necesite sobrecargar uno de esos operadores binarios que podrían estar sobrecargados como miembros o no miembros, debe tomar esta decisión).
Sin embargo, existen diferencias sutiles entre y.func(v)
y func(y,v)
, debido a que C++ trata el argumento this
, el argumento que se pasa por escrito antes de que el .
(el punto), diferente de los otros argumentos, y lo hace de muchas maneras .
Como has descubierto, el argumento this
podría ser un valor de lado derecho (temporal) incluso para const
funciones no miembros, mientras que para los otros argumentos, una referencia no constante evita rvalues quede vinculado a la discusión.Además, es el argumento this
tipo en tiempo de ejecución podría influir en qué función se llama (para virtual
miembros), mientras que los otros argumentos de tipo en tiempo de ejecución es irrelevante, porque se elige una función sólo en función de su tipo en tiempo de compilación solamente. Y las conversiones implícitas solo se aplican a los argumentos explícitos de las funciones miembro, pero nunca a su argumento implícito this
. (Es por eso que puede pasar una cadena literal para un const std::string&
, pero no se puede llamar std::string::size()
en una cadena literal.)
lo tanto, para concluir, a pesar del hecho de que lo que está antes de la .
termina como un argumento de función (implícita), en realidad es tratado de manera muy diferente de los otros argumentos de la función.
¿Por qué 'la referencia no constante no puede vincularse a un valor_r'? – yoyo
@yoyo: Esto se explica en [¿Por qué una referencia no constante no puede enlazarse a un objeto temporal?] (Http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot -bind-to-a-temporary-object) (especialmente la respuesta de sbi) –
Personalmente, considero que es una decisión muy incómoda en un lenguaje donde todo lo demás depende del programador. Me divierte un poco que la semántica de "movimiento" y las referencias "destructivas" asociadas permitan algo similar. –