¿Tiene sentido esta regla de análisis estático de C ++ como está?
Estoy implementando algunas reglas de análisis estático de C ++, y una de ellas prohíbe que una función devuelva una referencia o un puntero a un parámetro de referencia de la función, es decir, todas las siguientes no son compatibles:
int *f(int& x) { return &x; } // #1
const int *g(const int& x) { return &x; } // #2
int& h(int& x) { return x; } // #3
const int& m(const int& x) { return x; } // #4
La justificación dada para esto es que "Es un comportamiento definido por la implementación si el parámetro de referencia es un objeto temporal o una referencia al parámetro".
Sin embargo, esto me desconcierta, porque los operadores de flujo en C ++ están escritos de esta manera, por ejemplo.
std::ostream& operator<<(std::ostream& os, const X& x) {
//...
return os;
}
Creo que estoy bastante seguro de que los operadores de flujo en C ++ no muestran, en general, un comportamiento definido por la implementación, así que, ¿qué está pasando?
De acuerdo con mi entendimiento actual, espero que los números 1 y 3 estén bien definidos, sobre la base de que los temporales no pueden estar vinculados a referencias no constantes, por lo queint& x
se refiere a un objeto real que tiene una duración más allá del alcance de la función, por lo tanto, devolver un puntero o una referencia a ese objeto está bien. Espero que # 2 sea poco fiable, porque un temporal podría haber estado vinculado aconst int& x
, en cuyo caso tratar de tomar su dirección parecería un mal plan. No estoy seguro acerca del # 4; mi intuición es que eso también es potencialmente peligroso, pero no estoy seguro. En particular, no tengo claro qué pasaría en el siguiente caso:
const int& m(const int& x) { return x; }
//...
const int& r = m(23);