为什么可以通过引用为局部变量而不是临时变量返回函数? C ++

时间:2012-03-06 15:34:23

标签: c++ reference temporary

例如,这个函数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之后被销毁。

6 个答案:

答案 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)

问题在于语义上堆栈上的变量或堆上的变量之间没有区别等等。所以语言别无选择,只能允许它,即使它是未定义的行为。 在第一个例子中,你得到一个简单的编译错误,因为你试图绑定一个临时变量的引用,这可以被语言禁止。