Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

According to Herb Sutter's article http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/, the following code is correct:

#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;
}

i.e. the lifetime of v is extended to the lifetime of the v const reference. And indeed this compiles fine with gcc and clang and runs without leaks according to valgrind.

However, when I change the main function thusly:

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

it still compiles but valgrind warns me of invalid reads in the second line of the function due to the fact that the memory was free'd in the first line.

Is this standard compliant behaviour or could this be a bug in both g++ (4.7.2) and clang (3.5.0-1~exp1)?

If it is standard compliant, it seems pretty weird to me... oh well.

like image 984
mwnx Avatar asked Jan 01 '26 21:01

mwnx


1 Answers

There's no bug here except in your code.

The first example works because, when you bind the result of f() to v, you extend the lifetime of that result.

In the second example you don't bind the result of f() to anything, so its lifetime is not extended. Binding to a subobject of it would count:

[C++11: 12.2/5]: The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except: [..]

…but you're not doing that: you're binding to the result of calling a member function (e.g. operator[]) on the object, and that result is not a data member of the vector!

(Notably, if you had an std::array rather than an std::vector, then the code would be absolutely fine as array data is stored locally, so elements are subobjects.)

So, you have a dangling reference to a logical element of the original result of f() which has long gone out of scope.

Sorry for the horrid initializers but, well, blame C++.

like image 197
Lightness Races in Orbit Avatar answered Jan 03 '26 11:01

Lightness Races in Orbit



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!