2016-02-12 32 views
6

我想知道为什么返回本地对象的const reference是非法的,而只要您将它分配给const reference就返回local object是合法的?返回常量引用vs临时对象

vector<int> f_legal() { 
    vector<int> tempVec; 
    tempVec.push_back(1); 
    return tempVec; 
} 

const vector<int>& f_illegal() { 
    vector<int> tempVec; 
    tempVec.push_back(1); 
    return tempVec; 
} 

void g() { 
    const vector<int>& v1 = f_legal(); // legal 
    const vector<int>& v2 = f_illegal(); // illegal 
} 

编辑: 我的观点是,如果分配一个const裁判返回的本地变量是合法的,那么不应该指定一个const裁判的局部变量返回的常量裁判是合法的呢?

+2

@Ed Heal是的,它在C++中定义良好,本地const引用将延长它所绑定的临时对象的生命周期。 –

+2

@EdHeal是的,这是合法的。标准中有一个特殊情况,只要在当前范围内有一个const引用,就会保持本地对象的活动。 –

回答

6

即使您将它分配给常量引用,返回值也会被声明为按值传递,这意味着它将作为临时对象复制到外部,然后绑定到常量引用。将临时对象绑定到const引用是好的,该对象不会被销毁,直到超出const引用的生命周期。

另一方面,返回局部变量的引用是非法的。当函数返回时,局部变量将被销毁,这意味着外部引用将被悬置。

编辑

我的观点是,如果分配一个const裁判返回的本地变量是合法的,那么不应该以一个局部变量返回的常量裁判指派一个const裁判是合法的好?

点是第一种情况下并不分配一个const裁判返回的局部变量,它分配一个常量裁判返回的临时变量。 (这可能从本地变量复制。)


[1]副本可能根据RVO技术上被省略。

+0

你确定情况总是如此吗?即使考虑“RVO/NRVO”? –

+0

@JamesAdkison:会有一个临时对象,并且引用将绑定到该临时对象。该副本可能会被忽略(如果结果可以直接在临时构建)。 –

+0

@BenVoigt是的,那是我的观点(即复制可能会被忽略)。 –

8

返回对局部变量的引用是非法的(未定义行为)。期。没有constmutable子句。

这是因为本地函数变量具有自动存储持续时间。在函数退出后它们被“销毁”。如果该函数返回对这样一个变量的引用,那么该引用被称为悬而未决:它指的是不再存在的对象。

由于特殊的C++规则,第一个是合法的:初始化对prvalue的引用将该临时对象的生命周期延长到引用的生命周期。

+0

该规则实际上与'const'无关 - 任何直接绑定到临时对象的引用都会延长该临时对象的生命周期。在C++ 98中,其他规则规定只有const引用可以直接绑定到临时的,那些规则现在已经改变,这对于生命周期扩展规则具有多米诺骨牌效应。 –

+0

@BenVoigt这是我听到的第一个。你能提供一个参考吗? – bolov

+0

请参阅http://stackoverflow.com/a/3716360/103167 –

1

很可能是因为它会彻底破坏整个基于堆栈的调用约定,这些约定几乎为我们服务了几十年......几乎每一个CPU都假设。