We all know that things like this are valid in c++:
const T &x = T();
while:
T &x = T();
is not.<
It prints 10 every time.
Modify the main function a little and it won't print 10 anymore:
int main()
{
B* p = f();
cout << "C++\n"; // prints C++
p->b(); // prints 4077568
}
how does this link gets established at what level?
See 12.2 [class.temporary] §4 and §5:
Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created.
There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is [...]
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 parameter in a function call persists until the completion of the full-expression containing the call.
So in your case, the temporary is destroyed after the evaluation of the full-expression new B(A(10))
.
You just got lucky. Changing B::b to this:
void b() {
int i = rand();
int j = rand();
cout << _a << endl;
}
prints out random numbers.
It simply demonstrates that analyzing language behavior by "trying it in the compiler" doesn't normally produce any useful results. Both of your examples are invalid for the very same reason.
The lifetime of the temporary is only extended when you use that temporary as the direct initializer for a const reference - only that will establish a "lifetime" link between the reference and the temporary.
Trying to pass a temporary as a constructor's argument and attaching a const reference inside the constructor will not establish the aforementioned link and will not extend the lifetime of the temporary.
Also, in accordance with C++ standard, if you do this
struct S {
const int &r;
S() : r(5) {
cout << r; // OK
}
};
the lifetime of the temporary is only extended to the end of the constructor. Once the constructor is finished, the temporary dies, meaning that this
S s;
cout << s.r; // Invalid
is invalid.
Your experiment with int
simply "appears to work", purely by accident.