Возврат ссылки сам по себе не приводит к неопределенному поведению, но если вы попытаетесь изменить его, вы это сделаете.
Доступ к объекту за пределами его времени жизни - неопределенное поведение.
int* foo(void) {
int a = 17; // a has automatic storage duration
return &a;
} // lifetime of a ends
int main(void) {
int* p = foo(); // p points to an object past lifetime ("dangling pointer")
int n = *p; // undefined behavior
}
http://en.cppreference.com/w/c/language/lifetime
Если у вас есть доступ к C ++ 17, вы можете реализовать его, используя std :: необязательно .Обратите внимание на использование std :: reference_wrapper , потому что использование ссылки в std::optional
делает вашу программу некорректной.
std::optional<std::reference_wrapper<record>> get_record(int key) {
if (valid(key))
return std::optional<std::reference_wrapper<record>>(lookup(key));
else
return std::nullopt;
}
Без C ++ 17 вы можете просто вернутьуказатель на вашу запись:
record* get_record(int key) {
if (valid(key))
return &lookup(key);
else
return nullptr;
}
Или, если вы предпочитаете, вы можете сохранить ссылочный тип возврата и выдать исключение, чтобы указать отсутствующую запись.Хотя это мой наименее предпочтительный подход, так как он позволяет легко вызывать get_record
без переноса в try / catch
.
record& get_record(int key) {
if (valid(key))
return &lookup(key);
else
throw std::out_of_range("Invalid record key!");
}