4

So from a question asked in another thread, I have thought of a new question and the answer is not obvious to me.

So it appears there is a c++ rule that says if you have a const reference to a temporary, then the lifetime of the temporary is at least as long as the const reference. But what if you have a local const reference to another object's member variable and then when you leave scope - Does it call the destructor of that variable?

So here is modified program from the original question:

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

class A {
public:
   A(std::string l) { k = l; };
   std::string get() const { return k; };
   std::string k;
};

class B {
public:
   B(A a) : a(a) {}
   void b() { cout << a.get(); }  //Has a member function
   A a;
};

void f(const A& a)
{  //Gets a reference to the member function creates  a const reference
     stores it and goes out of scope
 const A& temp = a;
 cout << "Within f(): " << temp.k << "\n";
}

int main() {
   B b(A("hey"));

   cout << "Before f(): " << b.a<< "\n";

   f(b.a);

   cout << "After f(): " << b.a.k << "\n";

   return 0;
}

So when I run this code, I get "hey" as the value everytime. Which seems to imply that a local const reference does not bind itself through life with a passed in member object. Why doesn't it?

Community
  • 1
  • 1
nndhawan
  • 597
  • 6
  • 24
  • So you expect the destructor of `b.a` being called when `temp` goes out of scope? So b would then contain a destructed member? – Henrik Apr 13 '12 at 13:08
  • What do you expect? I don't see any reason that b.a will be changed. – Cosyn Apr 13 '12 at 13:16
  • see http://stackoverflow.com/questions/3097593/what-happens-when-c-reference-leaves-its-scope – EdChum Apr 13 '12 at 13:17

2 Answers2

10

b.a is not a temporary so its lifetime is not affected by any references that are subsequently bound to it.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • That makes sense, but how would the compiler track its not a temporary? Does it know where data is stored on the stack or on the heap? How does it know that there are multiple references tied to that memory location? I know I am asking a lot of questions but I'm a new to C++ and its compilers, so please forgive my curiousity. – nndhawan Apr 13 '12 at 14:29
  • @nndhawan: The compile looks at the expression `b.a`. It refers to an existing object, it is an _lvalue_. This is determined at compile time. It doesn't matter where the object is actually stored at run time. – CB Bailey Apr 13 '12 at 14:40
  • There seems to be some basic confusion here (probably because the standard itself is poorly worded). The only time the lifetime of a temporary is extended is when the temporary itself is used to initialize a reference. At which point in time, the compiler can see both the temporary and the reference, and so knows what to do. Initializing a reference from another reference does _not_ extend the lifetime of any temporary bound to the source reference. – James Kanze Apr 13 '12 at 14:44
2

I'm not sure I understand what you're asking. In your code, the only temporary I see is the A("hey") in the expression that initializes b in main. And that is copied (using the copy constructor) into b.a in B::B. After that, there are no more temporaries, anywhere.

More generally, the fact that a temporary is bound to a reference doesn't necessarily change its lifetime. What extends the lifetime is the fact that the temporary is used to initialize the reference: in your case, for example, temp in f will never have an effect on the lifetime of a temporary, because it is not initialized with a temporary, but with another reference. And there are exceptions to this rule: if you use a temporary to initialize a member reference in the initializers of a class, it's lifetime will still not extend beyond the end of the constructor, so:

class A
{
    std::string const& rString;
public:
    A() : rString( std::string( "hey" ) ) {}
    std::string get() const { retur rString; }
};

will not work.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Ok I see what, in general, everyone is saying. But I don't get why this example won't work. It seems counter intutive, how else would you initialize rString? – nndhawan Apr 13 '12 at 15:57
  • @nndhawan Not with a temporary. If your class has a reference, then this reference has to refer to something obtained from outside of the class: the constructor takes a reference as an argument (and the lifetime issues are the responsibility of the client---be sure to document them), or to something looked up elsewhere (e.g. configuration data). In practice, however, having a reference as a member should be very rare. The general solution would be for all members to be values, not references. – James Kanze Apr 13 '12 at 16:09