例如,这个函数f定义如下:
int f(int x){return x;}
如您所知您无法为此临时int指定引用:
int& rf=f(2);// this will give an error
但如果我重新定义了我的函数f:
int& f(int x){return x;}
f(2);// so now f(2) is a reference of x, which has been destroyed
所以我的问题是:如何编译器不允许你创建一个临时的引用,它将在statment之后被销毁(在第一种情况下为int)。另一方面,它允许你创建一个引用f(2)到x
,而编译器知道这个将在return
之后被销毁。
答案 0 :(得分:7)
返回对本地的引用是编译器难以或不可能检测的内容。例如:
int & f()
{
int x;
extern int & g(int & x);
// Does this return a reference to "x"?
// The compiler has no way to tell.
return g(x);
}
即使不调用外部函数,仍然很难分析复杂的程序流,以判断返回的引用是否是本地的;而不是试图定义什么算“足够简单”来诊断,标准不需要诊断 - 它只是声明它给出了未定义的行为。一个好的编译器应该发出警告,至少在简单的情况下。
将临时引用绑定到非const引用是编译器可以轻松检测的内容,因此标准需要对其进行诊断。
答案 1 :(得分:1)
因为,正如标准所规定的那样,从函数返回对临时变量的引用是未定义的行为。
实际上功能定义有什么问题:
int& f(int x)
{
return x;
}
答案 2 :(得分:1)
您可以将临时右值绑定到const引用以延长它的生命周期。
const int& rf=f(2);
答案 3 :(得分:1)
要拒绝您的第一个代码段,编译器会应用您不能直接将临时绑定到非const引用的简单规则。
要拒绝第二个,编译器可能会应用一个规则,即通过引用返回的函数的return
语句不能是自动变量的名称(包括按值函数参数)。在我看来,这也是一个相当容易的规则。
我不知道为什么标准没有说明这样做是不正确的。我无法想到它的任何有效用途,但也许在第一个标准时它会对某些实现或其他实施造成过重负担。或者也许感觉它只有一半的修复而且不值得打扰(还有很多其他方法来创建一个悬空引用,这只会阻止其中一个)。
标准通常不会阻止您创建绑定到临时的非const引用的原因是有时它可以正常运行。例如:
struct Foo {
static void set(Foo &f) { f.val = 0; }
int val;
int bar() {
set(*this);
return val;
}
};
std::cout << Foo().bar() << "\n";
这里Foo()
是临时的,行set(*this)
将它绑定到非const引用(但不直接,它使用左值表达式*this
引用临时的一些时间而不是其他)。这里没有问题,临时超过了参考。因此,语言以某种方式阻止任何临时绑定到任何非const引用将是不必要的限制。
答案 4 :(得分:0)
通过引用返回并不是一个好主意,除非您确定您返回的引用仍将指向有效的引用。
否则,预计会出现未定义的行为。
因为变量是本地变量,所以可以确定引用无效
答案 5 :(得分:0)
问题在于语义上堆栈上的变量或堆上的变量之间没有区别等等。所以语言别无选择,只能允许它,即使它是未定义的行为。 在第一个例子中,你得到一个简单的编译错误,因为你试图绑定一个临时变量的引用,这可以被语言禁止。