返回const引用vs临时对象

时间:2016-02-12 16:52:17

标签: c++ reference const

我想知道为什么返回本地对象的for(var i = 0;i < data.length;i++) { data[i] = {title: data[i]} } 是非法的,而只要将const reference分配给local object,返回const reference是合法的?

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 ref赋给返回的局部变量是合法的,那么不应该将const ref分配给局部变量的返回const ref也是合法的吗?

3 个答案:

答案 0 :(得分:10)

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

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

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

答案 1 :(得分:8)

即使将其赋值给const引用,返回值也会声明为按值传递,这意味着它将作为临时对象复制到 [1] 外部,然后绑定到const引用。将临时对象绑定到 const 引用很好,在超出const引用的生命周期之前,对象不会被销毁。

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

修改

  

我的观点是,如果将const ref赋给返回的局部变量是合法的,那么不应该将const ref分配给局部变量的返回const ref也是合法的吗?

关键是第一种情况是没有将const ref分配给返回的局部变量,它将const ref分配给返回的临时变量。 (可能从局部变量复制。)

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

答案 2 :(得分:1)

最有可能的原因是它会完全破坏整个基于堆栈的调用约定,这些约定几十年来一直很好用......几乎每个CPU都假定它。