Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Const reference as class member

Even if the subject was discussed many times around here, I can't find a conclusive explanation regarding my particular case. Will const extend the lifetime of the RefTest temporary? Is the below example legal?

#include <iostream>

class RefTest
{
public:
    RefTest(const std::string &input) : str(input) {}
    ~RefTest () {std::cout << "RefTest" << std::endl;}
private:
    std::string str;
};

class Child
{
public:
    Child (const RefTest &ref) : ref_m(ref) {}
    ~Child () {std::cout << "Test" << std::endl;}
private:
    const RefTest &ref_m;
};

class Test
{
public:
    Test () : child(RefTest("child")) {}//Will the temporary get destroyed here?
    ~Test () {std::cout << "Test" << std::endl;}
private:
    const Child child;
};

int main ()
{
   Test test;
}
like image 468
Mihai Todor Avatar asked Mar 20 '13 01:03

Mihai Todor


2 Answers

The C++ standard states:

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 to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below. A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits. A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call.

NOTE: And by the way, this is duplicate (1, 2), you should search better, next time... :)

like image 50
Alexander Shukaev Avatar answered Nov 05 '22 23:11

Alexander Shukaev


The reference does not extend the lifetime. The code is legal, but only because you never access ref_m after the constructor finishes.

The temporary is bound to the constructor parameter, ref. Binding another reference to it later, ref_m, doesn't extend the lifetime. If it did, you'd have an object on the stack which has to persist as long as the reference member it's bound to, which could be allocated on the heap, so the compiler would be unable to unwind the stack when the constructor returns.

It would be nice to get a warning, but compilers aren't perfect and some things are difficult to warn about. The temporary is created in a different context from where it's bound to a reference, so the compiler can only tell there's a problem with inlinging turned on, or some clever static analysis.

like image 35
Jonathan Wakely Avatar answered Nov 05 '22 22:11

Jonathan Wakely