1

Herb Sutter:

Effective Concurrency: Use Lock Hierarchies to Avoid DeadlockEffective Concurrency: Break Amdahl’s Law! » GotW #88: A Candidate For the “Most Important const” 2008-01-01 by Herb Sutter A friend recently asked me whether Example 1 below is legal, and if so what it means. It led to a nice discussion I thought I’d post here. Since it was in close to GotW style already, I thought I’d do another honorary one after all these years… no, I have not made a New Year’s Resolution to resume writing regular GotWs. :-)

JG Questions Q1: Is the following code legal C++?

// Example 1

string f() { return "abc"; }

void g() {
const string& s = f();
  cout << s << endl;    // can we still use the "temporary" object?
}

A1: Yes. This is a C++ feature… the code is valid and does exactly what it appears to do.

Normally, a temporary object lasts only until the end of the full expression in which it appears. However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself, and thus avoids what would otherwise be a common dangling-reference error. In the example above, the temporary returned by f() lives until the closing curly brace. (Note this only applies to stack-based references. It doesn’t work for references that are members of objects.)

Originally, I think the final sentence means:

class A 
{
public:
    int x;
    A(const int& x_)
    {
        x = x_;
    }
};

int main()
{
    A a(1); // assign lvalue to const int&
    std::cout << a.x;
}

However, it works fine apparently.

So, what "does It doesn’t work for references that are members of objects" means?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • isn't what Sutter is referring to regarding if the member is a reference? e.g. `int& x;` You've defined it `x` to be a plain member – EdChum Aug 02 '17 at 12:08
  • That member isn't a reference, but it might "apparently" work fine even if it were, due to the wonders of undefined behaviour. – molbdnilo Aug 02 '17 at 12:18
  • @molbdnilo the way I evoke `A a(1)` is UB? can you express in detail? thanks in advance. – Chen Li Aug 02 '17 at 12:25
  • @czxyl It's not undefined, because your member is not a reference. But you can't tell from observing a program's execution that it *isn't* undefined. – molbdnilo Aug 02 '17 at 12:32

1 Answers1

5

It means that if you do something like this:

string f() { return "abc"; }

struct foo {
  string const & _s;
  foo() : _s(f()) {}
};

It won't extend the life of the temporary returned from f. And the reference _s will dangle.

Extending the lifetime of temporaries is a property of references with automatic storage duration. I.e. local variables in function scope.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458