C++ - "最重要的const"不适用于表达式?

mwn*_*wnx 3 c++ reference compiler-bug

根据Herb Sutter的文章http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/,以下代码是正确的:

#include <iostream>
#include <vector>
using namespace std;

vector<vector<int>> f() { return {{1},{2},{3},{4},{5}}; }

int main()
{
    const auto& v = f();
    cout << v[3][0] << endl;
}
Run Code Online (Sandbox Code Playgroud)

即生命周期v延长到vconst参考的生命周期.事实上,根据valgrind的说法,这可以很好地用gcc和clang编译而且没有泄漏.

但是,当我main这样改变功能时:

int main()
{
    const auto& v = f()[3];
    cout << v[0] << endl;
}
Run Code Online (Sandbox Code Playgroud)

它仍然编译,但valgrind警告我函数的第二行中的无效读取,因为第一行中的内存是空闲的.

这是符合标准的行为还是g ++(4.7.2)和clang(3.5.0-1~exp1)中的错误?

如果它符合标准,对我来说似乎很奇怪......哦.

Lig*_*ica 11

除了代码之外,这里没有任何错误.

第一个示例,因为当你绑定的结果f()v,来扩展该结果的寿命.

在第二个示例中,您不会将结果绑定f()到任何内容,因此不会延长其生命周期.绑定到它的子对象将计数:

[C++11: 12.2/5]:第二个上下文是引用绑定到临时的.引用绑定的临时值作为绑定引用的子对象的完整对象的临时值在引用的生命周期内持续存在,除了:[..]

...但你没有这样做:你绑定到operator[]在对象上调用成员函数(例如)的结果,并且该结果不是向量的数据成员!

(值得注意的是,如果你有一个std::array而不是一个std::vector,那么代码绝对没问题,因为数组数据存储在本地,因此元素是子对象.)

因此,您对原始结果的逻辑元素的悬空引用f()已经超出了范围.

抱歉可怕的初始化器,但是,好吧,责怪C++.