4.13.7 Asignación a funciones
§1 Sinopsis
Hemos señalado repetidamente que los valores devueltos por funciones no son direccionables porque son variables de registro ( 4.4.7). Además por lo general, salvo cuando devuelven una referencia, tampoco son asignables porque no constituyen Lvalues. Por esta razón, es normal ver las invocaciones de funciones aisladas, o a la derecha de expresiones de asignación, cuando se utilizan para asignar a una variable el valor devuelto por la función. Son expresiones del tipo:
func1(x);
y = func2();
Sin embargo, cuando el valor devuelto es un Lvalue, pueden ser asignadas directamente. En estos casos el compilador crea un objeto temporal adecuado. Es el caso del ejemplo que sigue:
int& foo(int& x) { ++x; return x; }
int main() {
int x = 3;
cout << foo(x); // -> 4
++foo(x);
cout << x; // -> 6
...
}
§2 Si el valor devuelto es un puntero a miembro, entonces también es posible realizar asignaciones
utilizando la invocación de la función:
struct E {
int x;
int* func() { return &x; }
};
int main() {
E e1 = {1};
cout << e1.x; // -> 1
*e1.func() = 2;
cout << e1.x; // -> 2
++*e1.func();
cout << e1.x; // -> 3
...
}
§3 También es posible realizar asignaciones a la invocación de la función si esta devuelve una referencia:
struct E {
int x;
int& func() { return x; }
};
int main() {
E e1 = {1};
cout << e1.x; // -> 1
e1.foo() = 10;
cout << e1.x; // -> 10
++e1.foo();
cout << e1.x; // -> 11
...
}
§4 Otro caso similar al anterior, utilizando una función externa en lugar de un método:
struct E {
int x;
};
int& foo(E& e) { return e.x; }
int main() {
E e1 = {1};
cout << e1.x; // -> 1
foo(e1) = 20 ;
cout << e1.x; // -> 20
++foo(e1);
cout << e1.x; // -> 21
...
}
§5 También son válidas las asignaciones cuando se devuelve un puntero al objeto:
struct E { int x; };
E* newObject() {
E* eptr = new E;
return eptr;
}
int main() {
newObject()->x = 22; // Ok. asignación permitida
...
}