While asking this question, I learned const reference to a temporary object is valid in C++:
int main ()
{
int a = 21;
int b = 21;
//error: invalid in
My original example is complex.
Therefore I post here a simpler example and I provide the corresponding ISO C++ standard paragraph.
This simpler example is also available on coliru.stacked-crooked.com/
#include
struct A
{
A(int i) { std::cout<<"Cstr "<< i<<'\n'; p = new int(i); }
~A() { std::cout<<"Dstr "<<*p<<'\n'; delete p; }
const A& thiz() const { return *this; }
int *p;
};
const A& constref( const A& a )
{
return a;
}
int main()
{
const A& a4 = A(4);
const A& a5 = A(5).thiz();
const A& a6 = constref( A(6) );
std::cout << "a4 = "<< *a4.p <<'\n';
std::cout << "a5 = "<< *a5.p <<'\n';
std::cout << "a6 = "<< *a6.p <<'\n';
}
The output using command line g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out:
Cstr 4
Cstr 5
Dstr 5
Cstr 6
Dstr 6
a4 = 4
a5 = 0
a6 = 0
Dstr 4
As you can see, the temporary objects referenced by a5 and a6 are destructed at the end of functions thiz and constref respectively.
This is an extract of §12.2 Temporary objects, where the bold part applies in this case:
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:
- 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.
- The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
- A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer.
This is a more complete example:
#include
struct A
{
A() { std::cout<<"Cstr 9\n"; p = new int(v = 9); }
A(int i) { std::cout<<"Cstr "<
And the corresponding output using same g++ command line:
---const A a1 = A(1)
Cstr 1
---const A a2 = A(2).thiz()
Cstr 2
Copy 2
Del 2 2
---const A a3 = constref( A(3) )
Cstr 3
Copy 3
Del 3 3
---const A& a4 = A(4)
Cstr 4
---const A& a5 = A(5).thiz()
Cstr 5
Del 5 5
---const A& a6 = constref( A(6) )
Cstr 6
Del 6 6
a1 = { *p=1 , v=1 }
a2 = { *p=12 , v=12 }
a3 = { *p=13 , v=13 }
a4 = { *p=4 , v=4 }
a5 = { *p=0 , v=5 }
a6 = { *p=0 , v=6 }
Del 4 4
Del 13 13
Del 12 12
Del 1 1