use*_*458 4 c++ reference temporary
我有一个函数返回对我的类"记录"的实例的引用.
record& get_record(int key) {
return lookup(key);
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,它返回一个引用而不是值.现在我稍微修改一下.
record& get_record(int key) {
if (valid(key))
return lookup(key);
else {
record x;
x.valid=false;
return x; //Here I really want to return a temporary variable
// and not a reference to a local variable.
}
}
Run Code Online (Sandbox Code Playgroud)
返回对局部变量的引用不是一个好主意是否正确?以及如何以一种临时变量的方式返回x?
返回对局部变量的引用不是一个好主意是否正确?
是.离开函数时将破坏本地对象,因此返回的引用始终是悬空的.
你可以做x一个static变量.
record& get_record(int key) {
if (valid(key))
return lookup(key);
else {
static record x;
x.valid=false;
return x;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,返回的引用将始终引用同一个对象,即x.
这比一个坏主意更糟糕,它是未定义的行为并导致大多数情况发生崩溃.这很糟糕(TM).
您可以做的是更改返回类型,get_record以便返回智能指针.如果key有效,则返回一个指向它的观察者指针.否则,它返回一个拥有一个新创建的对象的智能指针:
#include <memory>
#include <iostream>
struct record { int n; } some_record{42};
std::shared_ptr<record> get_record(bool b)
{
if (b == true) {
return std::shared_ptr<record>{&some_record, [](record*){}}; // see explanation ^1
}
return std::shared_ptr<record>{new record{0}};
}
int main()
{
std::cout << get_record(true)->n << "\n"; // this is some_record
std::cout << get_record(false)->n << "\n"; // this is a temporary
}
Run Code Online (Sandbox Code Playgroud)
1)关于[](record*){}:std::shared_ptr::shared_ptr()当智能指针被销毁时,作为第二个参数给出的这个no-op lambda 被调用.它取代了默认的删除操作,std::shared_ptr其行为是调用delete拥有的指针.
关于你的设计有缺陷的原因.事实上,将get_record返回作为参考使其不一致.你想要的是:
key有效则返回对现有/永久对象的引用,和这两个是互斥的,你的功能没有意义:什么get_record回归语义?