6

I am looking at code of the following form:

class foo
{
  public:
    foo() {}

  //...
};

class bar
{
  public:
    bar() : ref() {}

  private:
    const foo &ref;
};

Is initializing a reference using a temporary in this way correct? I know that it is possible to initialize a const reference that's a local variable with a temporary, and that doing so extends the lifetime of the temporary, e.g.

const foo &tmp = funcThatReturnsByValue(); //OK

However, one of the answers to the related initialize reference in initialization list suggests that there is a difference between "short-lived" and "long-lived" references, and that initializing ref as above is undefined behavior (even though ref is a const reference).

12.2.5 in the standard says, in part, "A temporary bound to a reference member in a constructor's ctor-initializer persists until the constructor exits." Is that describing this situation?

Community
  • 1
  • 1
user168715
  • 5,469
  • 1
  • 31
  • 42
  • Could you fix your code so that it actually involves a temporary? – Cheers and hth. - Alf Nov 10 '10 at 19:34
  • ref() doesn't bind ref to a temporary instance of foo? Sorry if my terminology is imprecise... I'm doing my best to understand this code snippet. – user168715 Nov 10 '10 at 19:42
  • Maybe this comment is worthless (I don't know the context you're looking at this code in), but the problem disappears if `ref` is a pointer. The point is that references cannot be value-initialized, but pointers can (they get zero-initialized). Moreover, most compilers (at least MSVC) issue a warning for being unable to generate a default assignment operator. As a guideline, whenever you want a reference member, you want actually a pointer... – Alexandre C. Nov 10 '10 at 21:03
  • The extension of the temporary's lifetime doesn't seem to be so dependable, after all: http://stackoverflow.com/questions/2604206/c-constant-reference-lifetime. It seems to be concocted in order to allow temporaries created during type conversions to work correctly, but isn't intended for other uses. – rwong Nov 10 '10 at 21:13
  • @rwong: What do you mean it's not "so dependable?" It is dependable, but only under two circumstances, both of which are described in the question to which you've linked. – James McNellis Nov 10 '10 at 21:38
  • 1
    @James McNellis: the rule only applies when the result is a true temporary *of the caller* (hence the reason the asker names the function `funcThatReturnsByValue()` ) If the function returns by reference (or other stuff) instead of by value, then it is a temporary whose lifetime is controlled by something else (such as the called function) and would have been destroyed before it is returned. So, *temporary* has a narrow meaning, and is not apparent to people outside the C++ compiler circle. It also would not be apparent to any code reviewers. – rwong Nov 11 '10 at 07:35

3 Answers3

4

This code is ill-formed. You can't default initialize or value initialize a reference.

If you actually had an expression inside of ref(), then yes, 12.2.5 would apply and the temporary would be destroyed when the constructor exits.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
2

Your example isn't creating a temporary - to do that you need to change to:

    bar() : ref(foo()) {} 

Now you're binding the reference to a temporary, and that temporary object will be destroyed at the end of the constructor. Your reference will be invalid, and that is Not A Good Thing.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

I guess what you want to do is:

bar() : ref(foo()) {}

but don't naively think that the lifetime of a temporary is extended until there's a reference to it. No, it actually is not. So, whether const or not, you sould initialize the reference with a normal object.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434