Я реализую некоторые правила статического анализа С++, и один из них запрещает функции возвращать ссылку или указатель на ссылочный параметр функции, то есть все несоответствующие:
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
Обоснование, данное для этого, заключается в том, что "это поведение, определяемое реализацией, является ли ссылочный параметр временным объектом или ссылкой на параметр".
Я озадачен этим, однако, потому что потоковые операторы в С++ написаны таким образом, например
std::ostream& operator<<(std::ostream& os, const X& x) {
//...
return os;
}
Я думаю, что я уверен, что потоковые операторы на С++ вообще не демонстрируют поведение, определяемое реализацией, и что происходит?
По моему мнению, как и сейчас, я ожидал бы, что # 1 и # 3 будут хорошо определены, исходя из того, что временные лица не могут быть привязаны к неконстантным ссылкам, поэтому int& x
относится к реальному объекту который имеет продолжительность жизни за пределами функции, поэтому возвращение указателя или ссылки на этот объект в порядке. Я ожидал бы, что # 2 будет изворотливым, потому что временное могло быть привязано к const int& x
, и в этом случае попытка найти его адрес окажется плохим. Я не уверен в # 4 - мое чувство кишки в том, что это тоже потенциально опасно, но я не уверен. В частности, я не знаю, что произойдет в следующем случае:
const int& m(const int& x) { return x; }
//...
const int& r = m(23);