Re: non-const reference and const reference
Ben Voigt [C++ MVP] wrote:
"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:fk69pq$pti$1@news.datemas.de...
Ben Voigt [C++ MVP] wrote:
"George" <George@discussions.microsoft.com> wrote in message
news:593CA7FA-6B65-452D-B2D1-7486F3435D14@microsoft.com...
Hello everyone,
This is my understanding of non-const reference, const reference
and their relationships with lvalue/rvalue. Please help to review
whether it is correct
and feel free to correct me. Thanks.
1. A const reference can be binded to a rvalue, for example, a
temporary object. And the "life" of the temporary object is
guaranteed to be extended
and we can safely operate through the const-reference.
No, the lifetime of the temporary object is only extended up to a
limit (the enclosing block), certain uses are not safe.
The limit you're talking about is the lifetime of the reference.
If I create a dynamic object with a member that is a reference to
T and initialise that reference with some temporary of type T,
and then I never delete that dynamic object, the temporary should
survive until the program ends (regardless of scopes, etc.)
This IS what I was talking about in my second point, if I understand
you correctly.
Are you saying this is safe?
class MakeARef
{
const std::complex<double>& m_ref;
public:
// here we use a reference to bind a member reference in a
ctor-initialization-list, which I think is bad news if the reference
is to a temporary
MakeARef(const std::complex<double>& ref) : m_ref(ref) {}
No, by no means it's safe. You have 'ref' (the only argument for the
constructor) initialised and bound to a temporary. But then you try
to initialise 'm_ref' with it, and *that* is going to be the problem
because the state of being bound to a temporary is not transferred
from a ref to a ref. The same goes when you try to return a const
ref and then initialise another const ref outside of the function
call:
const int& foo() { return 42; }
int main() {
const int& f = foo();
return f; // ain't gonna work, 'f' is invalid here
}
It would be slightly different if you had
MakeARef(std::complex<double> temp) : m_ref(temp) {}
BUT, since the binding happens in a c-tor initialiser, the temp
will live only until the end of the constructor call. See
[class.temporary]/5.
Which brings up an interesting problem, how does one create
a reference as part of a "new'ed" object without it falling into
the same exception (ref initialised with a temporary in a class
initialiser list)? I am not certain I can find a way shortly,
and I am not going to try, maybe there isn't any...
};
MakeARef* f(std::complex<double> v)
{
return new MakeARef(v + 1);
}
You're saying that the compiler magically allocates extra memory when
calling operator new, to hold the temporary?
Hell no. However, every temporary lives somewhere. The temporary
can be destroyed sooner or it can be held onto, depending on whether
there is a reference bound to it or not. If there is a reference,
then as soon as the reference dies (goes out of scope), the temporary
is also destroyed (respecting the order of static object creation
around that temporary).
This has nothing to do with 'operator new', really. It doesn't
matter how the temporary is created and how the reference keeps on
living.
And also magically
frees the extra memory when the referent is deleted?
How about using in-place initialization? Still extra memory reserved
and allocated?
Not sure what this is about. What's "in-place initialization"?
I'd appreciate a reference to the relevant section of the standard.
[class.temporary], I believe, covers it all.
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask