C++ - "Most important const"不适用于表达式?

C++ - "Most important const" doesn't work with expressions?

本文关键字:适用于 表达式 不适用 important Most C++ const      更新时间:2023-10-16

根据 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;
}

v的寿命延长至v常量基准的寿命。事实上,这在 gcc 和 clang 中编译得很好,并且根据 valgrind 运行没有泄漏。

但是,当我这样更改main函数时:

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

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

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

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

除了你的代码之外,这里没有错误。

第一个示例之所以有效,是因为当您将 f() 的结果绑定到 v 时,会延长该结果的生存期。

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

[C++11: 12.2/5]: 第二个上下文是当引用绑定到临时时。引用绑定到的临时或作为引用绑定到的子对象的完整对象的临时对象在引用的生存期内持续存在,但以下情况除外:[..]

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

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

因此,您对f()原始结果的逻辑元素有一个悬而未决的引用,该元素早已超出范围。

对不起可怕的初始化器,但好吧,责怪C++。