Is there any point naming a local variable as a rvalue-ref? - c++

Assuming the code compiles, is there any difference between:
A && a = .....
and
A & a = .....
? a is a local variable in a function or method, not a parameter.
By giving the rvalue-reference a name (a) it is effectively an lvalue for the rest of the scope? i.e. even with the former form, you'd have to use move(a) to enable pilfering when passing a to another function?
I appreciate there might be other problems with the second form, which prevent compilation, for example you can't have a (non-const) reference to a temporary. So, yes, I'm curious to know all the differences, but first I want to confirm my hunch that they are fully equivalent for the remainder of the scope.
Update: as an example of this 'temporary' problem, which #KerrekSB has reiterated, sometimes you must make the plain reference const. In that case, my question is whether there is a difference between:
const A && a = .....
and
const A & a = .....

There might be differences with operator A& and operator A&& being invoked in the one and other case respectively (You would need to check the spec and the DRs that modified/fixed that part of the spec).
What definitely is different is decltype(a) for both cases.

This works:
int foo();
int && a = foo();
This doesn't:
int & b = foo(); // error, cannot bind rvalue to non-const ref

The difference between A && a= ... and A & a= ... is that the former can bind to a temporary while the latter cannot. The C++ standard now specifies that a reference has to be non-volatile const or an rvalue reference to bind to a temporary (see 8.5.3 References [dcl.init.ref]), which can then extend the lifetime of the temporary (see 12.2 [class.temporary]).
EDIT: If you think about what rvalue references allow you to do, they have to be able to bind to temporaries, otherwise, you would not be able to express move semantics in C++.

(Answering my own question just to summarize what I think I've learned.)
In summary, what's the difference between A &a = ... and A &&a = ...? And between const A &a = ... and const A &&a = ...? If they are names of function parameters, then it affects function lookup clearly, but I'm just talking about local variables. The differences are:
(Obvious) const must be obeyed. A const reference can't be used to modify the object.
A &a = foo(); can't bind to a temporary (nothing new there), but the other three forms can and will extend the lifetime to the of the local variable.
decltype(a) will be different.
(Assuming there was no const problem), the initialization will likely be the same, except if there are operator & or operator && conversions to choose from.
In summary, there are fewer differences than I had originally assumed. Months ago, I had thought that
A &&a =...;
foo(a);
would call foo(A&&). But instead foo(move(a)) is required.
A C++03 programmer can fairly safely use A &&a = to extend the lifetime of temporaries without having to worry about other unexpected differences.
(Thanks to all)

Related

Are temporaries const? Pass by const reference [duplicate]

Why is it not allowed to get non-const reference to a temporary object,
which function getx() returns? Clearly, this is prohibited by C++ Standard
but I am interested in the purpose of such restriction, not a reference to the standard.
struct X
{
X& ref() { return *this; }
};
X getx() { return X();}
void g(X & x) {}
int f()
{
const X& x = getx(); // OK
X& x = getx(); // error
X& x = getx().ref(); // OK
g(getx()); //error
g(getx().ref()); //OK
return 0;
}
It is clear that the lifetime of the object cannot be the cause, because
constant reference to an object is not prohibited by C++ Standard.
It is clear that the temporary object is not constant in the sample above, because calls to non-constant functions are permitted. For instance, ref() could modify the temporary object.
In addition, ref() allows you to fool the compiler and get a link to this temporary object and that solves our problem.
In addition:
They say "assigning a temporary object to the const reference extends the lifetime of this object" and " Nothing is said about non-const references though".
My additional question. Does following assignment extend the lifetime of temporary object?
X& x = getx().ref(); // OK
From this Visual C++ blog article about rvalue references:
... C++ doesn't want you to accidentally
modify temporaries, but directly
calling a non-const member function on
a modifiable rvalue is explicit, so
it's allowed ...
Basically, you shouldn't try to modify temporaries for the very reason that they are temporary objects and will die any moment now. The reason you are allowed to call non-const methods is that, well, you are welcome to do some "stupid" things as long as you know what you are doing and you are explicit about it (like, using reinterpret_cast). But if you bind a temporary to a non-const reference, you can keep passing it around "forever" just to have your manipulation of the object disappear, because somewhere along the way you completely forgot this was a temporary.
If I were you, I would rethink the design of my functions. Why is g() accepting reference, does it modify the parameter? If no, make it const reference, if yes, why do you try to pass temporary to it, don't you care it's a temporary you are modifying? Why is getx() returning temporary anyway? If you share with us your real scenario and what you are trying to accomplish, you may get some good suggestions on how to do it.
Going against the language and fooling the compiler rarely solves problems - usually it creates problems.
Edit: Addressing questions in comment:
1) `X& x = getx().ref(); // OK when will x die?` - I don't know and I don't care, because this is exactly what I mean by "going against the language". The language says "temporaries die at the end of the statement, unless they are bound to const reference, in which case they die when the reference goes out of scope". Applying that rule, it seems x is already dead at the beginning of the next statement, since it's not bound to const reference (the compiler doesn't know what ref() returns). This is just a guess however.
I stated the purpose clearly: you are not allowed to modify temporaries, because it just does not make sense (ignoring C++0x rvalue references). The question "then why am I allowed to call non-const members?" is a good one, but I don't have better answer than the one I already stated above.
Well, if I'm right about x in X& x = getx().ref(); dying at the end of the statement, the problems are obvious.
Anyway, based on your question and comments I don't think even these extra answers will satisfy you. Here is a final attempt/summary: The C++ committee decided it doesn't make sense to modify temporaries, therefore, they disallowed binding to non-const references. May be some compiler implementation or historic issues were also involved, I don't know. Then, some specific case emerged, and it was decided that against all odds, they will still allow direct modification through calling non-const method. But that's an exception - you are generally not allowed to modify temporaries. Yes, C++ is often that weird.
In your code getx() returns a temporary object, a so-called "rvalue". You can copy rvalues into objects (aka. variables) or bind them to to const references (which will extend their life-time until the end of the reference's life). You cannot bind rvalues to non-const references.
This was a deliberate design decision in order to prevent users from accidentally modifying an object that is going to die at the end of the expression:
g(getx()); // g() would modify an object without anyone being able to observe
If you want to do this, you will have to either make a local copy or of the object first or bind it to a const reference:
X x1 = getx();
const X& x2 = getx(); // extend lifetime of temporary to lifetime of const reference
g(x1); // fine
g(x2); // can't bind a const reference to a non-const reference
Note that the next C++ standard will include rvalue references. What you know as references is therefore becoming to be called "lvalue references". You will be allowed to bind rvalues to rvalue references and you can overload functions on "rvalue-ness":
void g(X&); // #1, takes an ordinary (lvalue) reference
void g(X&&); // #2, takes an rvalue reference
X x;
g(x); // calls #1
g(getx()); // calls #2
g(X()); // calls #2, too
The idea behind rvalue references is that, since these objects are going to die anyway, you can take advantage of that knowledge and implement what's called "move semantics", a certain kind of optimization:
class X {
X(X&& rhs)
: pimpl( rhs.pimpl ) // steal rhs' data...
{
rhs.pimpl = NULL; // ...and leave it empty, but deconstructible
}
data* pimpl; // you would use a smart ptr, of course
};
X x(getx()); // x will steal the rvalue's data, leaving the temporary object empty
What you are showing is that operator chaining is allowed.
X& x = getx().ref(); // OK
The expression is 'getx().ref();' and this is executed to completion before assignment to 'x'.
Note that getx() does not return a reference but a fully formed object into the local context. The object is temporary but it is not const, thus allowing you to call other methods to compute a value or have other side effects happen.
// It would allow things like this.
getPipeline().procInstr(1).procInstr(2).procInstr(3);
// or more commonly
std::cout << getManiplator() << 5;
Look at the end of this answer for a better example of this
You can not bind a temporary to a reference because doing so will generate a reference to an object that will be destroyed at the end of the expression thus leaving you with a dangling reference (which is untidy and the standard does not like untidy).
The value returned by ref() is a valid reference but the method does not pay any attention to the lifespan of the object it is returning (because it can not have that information within its context). You have basically just done the equivalent of:
x& = const_cast<x&>(getX());
The reason it is OK to do this with a const reference to a temporary object is that the standard extends the lifespan of the temporary to the lifespan of the reference so the temporary objects lifespan is extended beyond the end of the statement.
So the only remaining question is why does the standard not want to allow reference to temporaries to extend the life of the object beyond the end of the statement?
I believe it is because doing so would make the compiler very hard to get correct for temporary objects. It was done for const references to temporaries as this has limited usage and thus forced you to make a copy of the object to do anything useful but does provide some limited functionality.
Think of this situation:
int getI() { return 5;}
int x& = getI();
x++; // Note x is an alias to a variable. What variable are you updating.
Extending the lifespan of this temporary object is going to be very confusing.
While the following:
int const& y = getI();
Will give you code that it is intuitive to use and understand.
If you want to modify the value you should be returning the value to a variable. If you are trying to avoid the cost of copying the obejct back from the function (as it seems that the object is copy constructed back (technically it is)). Then don't bother the compiler is very good at 'Return Value Optimization'
Why is discussed in the C++ FAQ (boldfacing mine):
In C++, non-const references can bind to lvalues and const references can bind to lvalues or rvalues, but there is nothing that can bind to a non-const rvalue. That's to protect people from changing the values of temporaries that are destroyed before their new value can be used. For example:
void incr(int& a) { ++a; }
int i = 0;
incr(i); // i becomes 1
incr(0); // error: 0 is not an lvalue
If that incr(0) were allowed either some temporary that nobody ever saw would be incremented or - far worse - the value of 0 would become 1. The latter sounds silly, but there was actually a bug like that in early Fortran compilers that set aside a memory location to hold the value 0.
The main issue is that
g(getx()); //error
is a logical error: g is modifying the result of getx() but you don't have any chance to examine the modified object. If g didn't need to modify its parameter then it wouldn't have required an lvalue reference, it could have taken the parameter by value or by const reference.
const X& x = getx(); // OK
is valid because you sometimes need to reuse the result of an expression, and it's pretty clear that you're dealing with a temporary object.
However it is not possible to make
X& x = getx(); // error
valid without making g(getx()) valid, which is what the language designers were trying to avoid in the first place.
g(getx().ref()); //OK
is valid because methods only know about the const-ness of the this, they don't know if they are called on an lvalue or on an rvalue.
As always in C++, you have a workaround for this rule but you have to signal the compiler that you know what you're doing by being explicit:
g(const_cast<x&>(getX()));
Seems like the original question as to why this is not allowed has been answered clearly: "because it is most likely an error".
FWIW, I thought I'd show how to it could be done, even though I don't think it's a good technique.
The reason I sometimes want to pass a temporary to a method taking a non-const reference is to intentionally throw away a value returned by-reference that the calling method doesn't care about. Something like this:
// Assuming: void Person::GetNameAndAddr(std::string &name, std::string &addr);
string name;
person.GetNameAndAddr(name, string()); // don't care about addr
As explained in previous answers, that doesn't compile. But this compiles and works correctly (with my compiler):
person.GetNameAndAddr(name,
const_cast<string &>(static_cast<const string &>(string())));
This just shows that you can use casting to lie to the compiler. Obviously, it would be much cleaner to declare and pass an unused automatic variable:
string name;
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
This technique does introduce an unneeded local variable into the method's scope. If for some reason you want to prevent it from being used later in the method, e.g., to avoid confusion or error, you can hide it in a local block:
string name;
{
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
}
-- Chris
Why would you ever want X& x = getx();? Just use X x = getx(); and rely on RVO.
The evil workaround involves the 'mutable' keyword. Actually being evil is left as an exercise for the reader. Or see here: http://www.ddj.com/cpp/184403758
Excellent question, and here's my attempt at a more concise answer (since a lot of useful info is in comments and hard to dig out in the noise.)
Any reference bound directly to a temporary will extend its life [12.2.5]. On the other hand, a reference initialized with another reference will not (even if it's ultimately the same temporary). That makes sense (the compiler doesn't know what that reference ultimately refers to).
But this whole idea is extremely confusing. E.g. const X &x = X(); will make the temporary last as long as the x reference, but const X &x = X().ref(); will NOT (who knows what ref() actually returned). In the latter case, the destructor for X gets called at the end of this line. (This is observable with a non-trivial destructor.)
So it seems generally confusing and dangerous (why complicate the rules about object lifetimes?), but presumably there was a need at least for const references, so the standard does set this behavior for them.
[From sbi comment]: Note that the fact that binding it to a const reference enhances a
temporary's lifetimes is an exception that's been added deliberately
(TTBOMK in order to allow manual optimizations). There wasn't an
exception added for non-const references, because binding a temporary
to a non-const reference was seen to most likely be a programmer
error.
All temporaries do persist until the end of the full-expression. To make use of them, however, you need a trick like you have with ref(). That's legal. There doesn't seem to be a good reason for the extra hoop to jump through, except to remind the programmer that something unusual is going on (namely, a reference parameter whose modifications will be quickly lost).
[Another sbi comment] The reason Stroustrup gives (in D&E) for disallowing the binding of
rvalues to non-const references is that, if Alexey's g() would modify
the object (which you'd expect from a function taking a non-const
reference), it would modify an object that's going to die, so nobody
could get at the modified value anyway. He says that this, most
likely, is an error.
"It is clear that the temporary object is not constant in the sample above, because calls
to non-constant functions are permitted. For instance, ref() could modify the temporary
object."
In your example getX() does not return a const X so you are able to call ref() in much the same way as you could call X().ref(). You are returning a non const ref and so can call non const methods, what you can't do is assign the ref to a non const reference.
Along with SadSidos comment this makes your three points incorrect.
I have a scenario I would like to share where I wish I could do what Alexey is asking. In a Maya C++ plugin, I have to do the following shenanigan in order to get a value into a node attribute:
MFnDoubleArrayData myArrayData;
MObject myArrayObj = myArrayData.create(myArray);
MPlug myPlug = myNode.findPlug(attributeName);
myPlug.setValue(myArrayObj);
This is tedious to write, so I wrote the following helper functions:
MPlug operator | (MFnDependencyNode& node, MObject& attribute){
MStatus status;
MPlug returnValue = node.findPlug(attribute, &status);
return returnValue;
}
void operator << (MPlug& plug, MDoubleArray& doubleArray){
MStatus status;
MFnDoubleArrayData doubleArrayData;
MObject doubleArrayObject = doubleArrayData.create(doubleArray, &status);
status = plug.setValue(doubleArrayObject);
}
And now I can write the code from the beginning of the post as:
(myNode | attributeName) << myArray;
The problem is it doesn't compile outside of Visual C++, because it's trying to bind the temporary variable returned from the | operator to the MPlug reference of the << operator. I would like it to be a reference because this code is called many times and I'd rather not have MPlug being copied so much. I only need the temporary object to live until the end of the second function.
Well, this is my scenario. Just thought I'd show an example where one would like to do what Alexey describe. I welcome all critiques and suggestions!
Thanks.

How a const reference bind to an object of a different type [duplicate]

Why is it not allowed to get non-const reference to a temporary object,
which function getx() returns? Clearly, this is prohibited by C++ Standard
but I am interested in the purpose of such restriction, not a reference to the standard.
struct X
{
X& ref() { return *this; }
};
X getx() { return X();}
void g(X & x) {}
int f()
{
const X& x = getx(); // OK
X& x = getx(); // error
X& x = getx().ref(); // OK
g(getx()); //error
g(getx().ref()); //OK
return 0;
}
It is clear that the lifetime of the object cannot be the cause, because
constant reference to an object is not prohibited by C++ Standard.
It is clear that the temporary object is not constant in the sample above, because calls to non-constant functions are permitted. For instance, ref() could modify the temporary object.
In addition, ref() allows you to fool the compiler and get a link to this temporary object and that solves our problem.
In addition:
They say "assigning a temporary object to the const reference extends the lifetime of this object" and " Nothing is said about non-const references though".
My additional question. Does following assignment extend the lifetime of temporary object?
X& x = getx().ref(); // OK
From this Visual C++ blog article about rvalue references:
... C++ doesn't want you to accidentally
modify temporaries, but directly
calling a non-const member function on
a modifiable rvalue is explicit, so
it's allowed ...
Basically, you shouldn't try to modify temporaries for the very reason that they are temporary objects and will die any moment now. The reason you are allowed to call non-const methods is that, well, you are welcome to do some "stupid" things as long as you know what you are doing and you are explicit about it (like, using reinterpret_cast). But if you bind a temporary to a non-const reference, you can keep passing it around "forever" just to have your manipulation of the object disappear, because somewhere along the way you completely forgot this was a temporary.
If I were you, I would rethink the design of my functions. Why is g() accepting reference, does it modify the parameter? If no, make it const reference, if yes, why do you try to pass temporary to it, don't you care it's a temporary you are modifying? Why is getx() returning temporary anyway? If you share with us your real scenario and what you are trying to accomplish, you may get some good suggestions on how to do it.
Going against the language and fooling the compiler rarely solves problems - usually it creates problems.
Edit: Addressing questions in comment:
1) `X& x = getx().ref(); // OK when will x die?` - I don't know and I don't care, because this is exactly what I mean by "going against the language". The language says "temporaries die at the end of the statement, unless they are bound to const reference, in which case they die when the reference goes out of scope". Applying that rule, it seems x is already dead at the beginning of the next statement, since it's not bound to const reference (the compiler doesn't know what ref() returns). This is just a guess however.
I stated the purpose clearly: you are not allowed to modify temporaries, because it just does not make sense (ignoring C++0x rvalue references). The question "then why am I allowed to call non-const members?" is a good one, but I don't have better answer than the one I already stated above.
Well, if I'm right about x in X& x = getx().ref(); dying at the end of the statement, the problems are obvious.
Anyway, based on your question and comments I don't think even these extra answers will satisfy you. Here is a final attempt/summary: The C++ committee decided it doesn't make sense to modify temporaries, therefore, they disallowed binding to non-const references. May be some compiler implementation or historic issues were also involved, I don't know. Then, some specific case emerged, and it was decided that against all odds, they will still allow direct modification through calling non-const method. But that's an exception - you are generally not allowed to modify temporaries. Yes, C++ is often that weird.
In your code getx() returns a temporary object, a so-called "rvalue". You can copy rvalues into objects (aka. variables) or bind them to to const references (which will extend their life-time until the end of the reference's life). You cannot bind rvalues to non-const references.
This was a deliberate design decision in order to prevent users from accidentally modifying an object that is going to die at the end of the expression:
g(getx()); // g() would modify an object without anyone being able to observe
If you want to do this, you will have to either make a local copy or of the object first or bind it to a const reference:
X x1 = getx();
const X& x2 = getx(); // extend lifetime of temporary to lifetime of const reference
g(x1); // fine
g(x2); // can't bind a const reference to a non-const reference
Note that the next C++ standard will include rvalue references. What you know as references is therefore becoming to be called "lvalue references". You will be allowed to bind rvalues to rvalue references and you can overload functions on "rvalue-ness":
void g(X&); // #1, takes an ordinary (lvalue) reference
void g(X&&); // #2, takes an rvalue reference
X x;
g(x); // calls #1
g(getx()); // calls #2
g(X()); // calls #2, too
The idea behind rvalue references is that, since these objects are going to die anyway, you can take advantage of that knowledge and implement what's called "move semantics", a certain kind of optimization:
class X {
X(X&& rhs)
: pimpl( rhs.pimpl ) // steal rhs' data...
{
rhs.pimpl = NULL; // ...and leave it empty, but deconstructible
}
data* pimpl; // you would use a smart ptr, of course
};
X x(getx()); // x will steal the rvalue's data, leaving the temporary object empty
What you are showing is that operator chaining is allowed.
X& x = getx().ref(); // OK
The expression is 'getx().ref();' and this is executed to completion before assignment to 'x'.
Note that getx() does not return a reference but a fully formed object into the local context. The object is temporary but it is not const, thus allowing you to call other methods to compute a value or have other side effects happen.
// It would allow things like this.
getPipeline().procInstr(1).procInstr(2).procInstr(3);
// or more commonly
std::cout << getManiplator() << 5;
Look at the end of this answer for a better example of this
You can not bind a temporary to a reference because doing so will generate a reference to an object that will be destroyed at the end of the expression thus leaving you with a dangling reference (which is untidy and the standard does not like untidy).
The value returned by ref() is a valid reference but the method does not pay any attention to the lifespan of the object it is returning (because it can not have that information within its context). You have basically just done the equivalent of:
x& = const_cast<x&>(getX());
The reason it is OK to do this with a const reference to a temporary object is that the standard extends the lifespan of the temporary to the lifespan of the reference so the temporary objects lifespan is extended beyond the end of the statement.
So the only remaining question is why does the standard not want to allow reference to temporaries to extend the life of the object beyond the end of the statement?
I believe it is because doing so would make the compiler very hard to get correct for temporary objects. It was done for const references to temporaries as this has limited usage and thus forced you to make a copy of the object to do anything useful but does provide some limited functionality.
Think of this situation:
int getI() { return 5;}
int x& = getI();
x++; // Note x is an alias to a variable. What variable are you updating.
Extending the lifespan of this temporary object is going to be very confusing.
While the following:
int const& y = getI();
Will give you code that it is intuitive to use and understand.
If you want to modify the value you should be returning the value to a variable. If you are trying to avoid the cost of copying the obejct back from the function (as it seems that the object is copy constructed back (technically it is)). Then don't bother the compiler is very good at 'Return Value Optimization'
Why is discussed in the C++ FAQ (boldfacing mine):
In C++, non-const references can bind to lvalues and const references can bind to lvalues or rvalues, but there is nothing that can bind to a non-const rvalue. That's to protect people from changing the values of temporaries that are destroyed before their new value can be used. For example:
void incr(int& a) { ++a; }
int i = 0;
incr(i); // i becomes 1
incr(0); // error: 0 is not an lvalue
If that incr(0) were allowed either some temporary that nobody ever saw would be incremented or - far worse - the value of 0 would become 1. The latter sounds silly, but there was actually a bug like that in early Fortran compilers that set aside a memory location to hold the value 0.
The main issue is that
g(getx()); //error
is a logical error: g is modifying the result of getx() but you don't have any chance to examine the modified object. If g didn't need to modify its parameter then it wouldn't have required an lvalue reference, it could have taken the parameter by value or by const reference.
const X& x = getx(); // OK
is valid because you sometimes need to reuse the result of an expression, and it's pretty clear that you're dealing with a temporary object.
However it is not possible to make
X& x = getx(); // error
valid without making g(getx()) valid, which is what the language designers were trying to avoid in the first place.
g(getx().ref()); //OK
is valid because methods only know about the const-ness of the this, they don't know if they are called on an lvalue or on an rvalue.
As always in C++, you have a workaround for this rule but you have to signal the compiler that you know what you're doing by being explicit:
g(const_cast<x&>(getX()));
Seems like the original question as to why this is not allowed has been answered clearly: "because it is most likely an error".
FWIW, I thought I'd show how to it could be done, even though I don't think it's a good technique.
The reason I sometimes want to pass a temporary to a method taking a non-const reference is to intentionally throw away a value returned by-reference that the calling method doesn't care about. Something like this:
// Assuming: void Person::GetNameAndAddr(std::string &name, std::string &addr);
string name;
person.GetNameAndAddr(name, string()); // don't care about addr
As explained in previous answers, that doesn't compile. But this compiles and works correctly (with my compiler):
person.GetNameAndAddr(name,
const_cast<string &>(static_cast<const string &>(string())));
This just shows that you can use casting to lie to the compiler. Obviously, it would be much cleaner to declare and pass an unused automatic variable:
string name;
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
This technique does introduce an unneeded local variable into the method's scope. If for some reason you want to prevent it from being used later in the method, e.g., to avoid confusion or error, you can hide it in a local block:
string name;
{
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
}
-- Chris
Why would you ever want X& x = getx();? Just use X x = getx(); and rely on RVO.
The evil workaround involves the 'mutable' keyword. Actually being evil is left as an exercise for the reader. Or see here: http://www.ddj.com/cpp/184403758
Excellent question, and here's my attempt at a more concise answer (since a lot of useful info is in comments and hard to dig out in the noise.)
Any reference bound directly to a temporary will extend its life [12.2.5]. On the other hand, a reference initialized with another reference will not (even if it's ultimately the same temporary). That makes sense (the compiler doesn't know what that reference ultimately refers to).
But this whole idea is extremely confusing. E.g. const X &x = X(); will make the temporary last as long as the x reference, but const X &x = X().ref(); will NOT (who knows what ref() actually returned). In the latter case, the destructor for X gets called at the end of this line. (This is observable with a non-trivial destructor.)
So it seems generally confusing and dangerous (why complicate the rules about object lifetimes?), but presumably there was a need at least for const references, so the standard does set this behavior for them.
[From sbi comment]: Note that the fact that binding it to a const reference enhances a
temporary's lifetimes is an exception that's been added deliberately
(TTBOMK in order to allow manual optimizations). There wasn't an
exception added for non-const references, because binding a temporary
to a non-const reference was seen to most likely be a programmer
error.
All temporaries do persist until the end of the full-expression. To make use of them, however, you need a trick like you have with ref(). That's legal. There doesn't seem to be a good reason for the extra hoop to jump through, except to remind the programmer that something unusual is going on (namely, a reference parameter whose modifications will be quickly lost).
[Another sbi comment] The reason Stroustrup gives (in D&E) for disallowing the binding of
rvalues to non-const references is that, if Alexey's g() would modify
the object (which you'd expect from a function taking a non-const
reference), it would modify an object that's going to die, so nobody
could get at the modified value anyway. He says that this, most
likely, is an error.
"It is clear that the temporary object is not constant in the sample above, because calls
to non-constant functions are permitted. For instance, ref() could modify the temporary
object."
In your example getX() does not return a const X so you are able to call ref() in much the same way as you could call X().ref(). You are returning a non const ref and so can call non const methods, what you can't do is assign the ref to a non const reference.
Along with SadSidos comment this makes your three points incorrect.
I have a scenario I would like to share where I wish I could do what Alexey is asking. In a Maya C++ plugin, I have to do the following shenanigan in order to get a value into a node attribute:
MFnDoubleArrayData myArrayData;
MObject myArrayObj = myArrayData.create(myArray);
MPlug myPlug = myNode.findPlug(attributeName);
myPlug.setValue(myArrayObj);
This is tedious to write, so I wrote the following helper functions:
MPlug operator | (MFnDependencyNode& node, MObject& attribute){
MStatus status;
MPlug returnValue = node.findPlug(attribute, &status);
return returnValue;
}
void operator << (MPlug& plug, MDoubleArray& doubleArray){
MStatus status;
MFnDoubleArrayData doubleArrayData;
MObject doubleArrayObject = doubleArrayData.create(doubleArray, &status);
status = plug.setValue(doubleArrayObject);
}
And now I can write the code from the beginning of the post as:
(myNode | attributeName) << myArray;
The problem is it doesn't compile outside of Visual C++, because it's trying to bind the temporary variable returned from the | operator to the MPlug reference of the << operator. I would like it to be a reference because this code is called many times and I'd rather not have MPlug being copied so much. I only need the temporary object to live until the end of the second function.
Well, this is my scenario. Just thought I'd show an example where one would like to do what Alexey describe. I welcome all critiques and suggestions!
Thanks.

What is the difference between these two versions of the same Template Class [duplicate]

Why is it not allowed to get non-const reference to a temporary object,
which function getx() returns? Clearly, this is prohibited by C++ Standard
but I am interested in the purpose of such restriction, not a reference to the standard.
struct X
{
X& ref() { return *this; }
};
X getx() { return X();}
void g(X & x) {}
int f()
{
const X& x = getx(); // OK
X& x = getx(); // error
X& x = getx().ref(); // OK
g(getx()); //error
g(getx().ref()); //OK
return 0;
}
It is clear that the lifetime of the object cannot be the cause, because
constant reference to an object is not prohibited by C++ Standard.
It is clear that the temporary object is not constant in the sample above, because calls to non-constant functions are permitted. For instance, ref() could modify the temporary object.
In addition, ref() allows you to fool the compiler and get a link to this temporary object and that solves our problem.
In addition:
They say "assigning a temporary object to the const reference extends the lifetime of this object" and " Nothing is said about non-const references though".
My additional question. Does following assignment extend the lifetime of temporary object?
X& x = getx().ref(); // OK
From this Visual C++ blog article about rvalue references:
... C++ doesn't want you to accidentally
modify temporaries, but directly
calling a non-const member function on
a modifiable rvalue is explicit, so
it's allowed ...
Basically, you shouldn't try to modify temporaries for the very reason that they are temporary objects and will die any moment now. The reason you are allowed to call non-const methods is that, well, you are welcome to do some "stupid" things as long as you know what you are doing and you are explicit about it (like, using reinterpret_cast). But if you bind a temporary to a non-const reference, you can keep passing it around "forever" just to have your manipulation of the object disappear, because somewhere along the way you completely forgot this was a temporary.
If I were you, I would rethink the design of my functions. Why is g() accepting reference, does it modify the parameter? If no, make it const reference, if yes, why do you try to pass temporary to it, don't you care it's a temporary you are modifying? Why is getx() returning temporary anyway? If you share with us your real scenario and what you are trying to accomplish, you may get some good suggestions on how to do it.
Going against the language and fooling the compiler rarely solves problems - usually it creates problems.
Edit: Addressing questions in comment:
1) `X& x = getx().ref(); // OK when will x die?` - I don't know and I don't care, because this is exactly what I mean by "going against the language". The language says "temporaries die at the end of the statement, unless they are bound to const reference, in which case they die when the reference goes out of scope". Applying that rule, it seems x is already dead at the beginning of the next statement, since it's not bound to const reference (the compiler doesn't know what ref() returns). This is just a guess however.
I stated the purpose clearly: you are not allowed to modify temporaries, because it just does not make sense (ignoring C++0x rvalue references). The question "then why am I allowed to call non-const members?" is a good one, but I don't have better answer than the one I already stated above.
Well, if I'm right about x in X& x = getx().ref(); dying at the end of the statement, the problems are obvious.
Anyway, based on your question and comments I don't think even these extra answers will satisfy you. Here is a final attempt/summary: The C++ committee decided it doesn't make sense to modify temporaries, therefore, they disallowed binding to non-const references. May be some compiler implementation or historic issues were also involved, I don't know. Then, some specific case emerged, and it was decided that against all odds, they will still allow direct modification through calling non-const method. But that's an exception - you are generally not allowed to modify temporaries. Yes, C++ is often that weird.
In your code getx() returns a temporary object, a so-called "rvalue". You can copy rvalues into objects (aka. variables) or bind them to to const references (which will extend their life-time until the end of the reference's life). You cannot bind rvalues to non-const references.
This was a deliberate design decision in order to prevent users from accidentally modifying an object that is going to die at the end of the expression:
g(getx()); // g() would modify an object without anyone being able to observe
If you want to do this, you will have to either make a local copy or of the object first or bind it to a const reference:
X x1 = getx();
const X& x2 = getx(); // extend lifetime of temporary to lifetime of const reference
g(x1); // fine
g(x2); // can't bind a const reference to a non-const reference
Note that the next C++ standard will include rvalue references. What you know as references is therefore becoming to be called "lvalue references". You will be allowed to bind rvalues to rvalue references and you can overload functions on "rvalue-ness":
void g(X&); // #1, takes an ordinary (lvalue) reference
void g(X&&); // #2, takes an rvalue reference
X x;
g(x); // calls #1
g(getx()); // calls #2
g(X()); // calls #2, too
The idea behind rvalue references is that, since these objects are going to die anyway, you can take advantage of that knowledge and implement what's called "move semantics", a certain kind of optimization:
class X {
X(X&& rhs)
: pimpl( rhs.pimpl ) // steal rhs' data...
{
rhs.pimpl = NULL; // ...and leave it empty, but deconstructible
}
data* pimpl; // you would use a smart ptr, of course
};
X x(getx()); // x will steal the rvalue's data, leaving the temporary object empty
What you are showing is that operator chaining is allowed.
X& x = getx().ref(); // OK
The expression is 'getx().ref();' and this is executed to completion before assignment to 'x'.
Note that getx() does not return a reference but a fully formed object into the local context. The object is temporary but it is not const, thus allowing you to call other methods to compute a value or have other side effects happen.
// It would allow things like this.
getPipeline().procInstr(1).procInstr(2).procInstr(3);
// or more commonly
std::cout << getManiplator() << 5;
Look at the end of this answer for a better example of this
You can not bind a temporary to a reference because doing so will generate a reference to an object that will be destroyed at the end of the expression thus leaving you with a dangling reference (which is untidy and the standard does not like untidy).
The value returned by ref() is a valid reference but the method does not pay any attention to the lifespan of the object it is returning (because it can not have that information within its context). You have basically just done the equivalent of:
x& = const_cast<x&>(getX());
The reason it is OK to do this with a const reference to a temporary object is that the standard extends the lifespan of the temporary to the lifespan of the reference so the temporary objects lifespan is extended beyond the end of the statement.
So the only remaining question is why does the standard not want to allow reference to temporaries to extend the life of the object beyond the end of the statement?
I believe it is because doing so would make the compiler very hard to get correct for temporary objects. It was done for const references to temporaries as this has limited usage and thus forced you to make a copy of the object to do anything useful but does provide some limited functionality.
Think of this situation:
int getI() { return 5;}
int x& = getI();
x++; // Note x is an alias to a variable. What variable are you updating.
Extending the lifespan of this temporary object is going to be very confusing.
While the following:
int const& y = getI();
Will give you code that it is intuitive to use and understand.
If you want to modify the value you should be returning the value to a variable. If you are trying to avoid the cost of copying the obejct back from the function (as it seems that the object is copy constructed back (technically it is)). Then don't bother the compiler is very good at 'Return Value Optimization'
Why is discussed in the C++ FAQ (boldfacing mine):
In C++, non-const references can bind to lvalues and const references can bind to lvalues or rvalues, but there is nothing that can bind to a non-const rvalue. That's to protect people from changing the values of temporaries that are destroyed before their new value can be used. For example:
void incr(int& a) { ++a; }
int i = 0;
incr(i); // i becomes 1
incr(0); // error: 0 is not an lvalue
If that incr(0) were allowed either some temporary that nobody ever saw would be incremented or - far worse - the value of 0 would become 1. The latter sounds silly, but there was actually a bug like that in early Fortran compilers that set aside a memory location to hold the value 0.
The main issue is that
g(getx()); //error
is a logical error: g is modifying the result of getx() but you don't have any chance to examine the modified object. If g didn't need to modify its parameter then it wouldn't have required an lvalue reference, it could have taken the parameter by value or by const reference.
const X& x = getx(); // OK
is valid because you sometimes need to reuse the result of an expression, and it's pretty clear that you're dealing with a temporary object.
However it is not possible to make
X& x = getx(); // error
valid without making g(getx()) valid, which is what the language designers were trying to avoid in the first place.
g(getx().ref()); //OK
is valid because methods only know about the const-ness of the this, they don't know if they are called on an lvalue or on an rvalue.
As always in C++, you have a workaround for this rule but you have to signal the compiler that you know what you're doing by being explicit:
g(const_cast<x&>(getX()));
Seems like the original question as to why this is not allowed has been answered clearly: "because it is most likely an error".
FWIW, I thought I'd show how to it could be done, even though I don't think it's a good technique.
The reason I sometimes want to pass a temporary to a method taking a non-const reference is to intentionally throw away a value returned by-reference that the calling method doesn't care about. Something like this:
// Assuming: void Person::GetNameAndAddr(std::string &name, std::string &addr);
string name;
person.GetNameAndAddr(name, string()); // don't care about addr
As explained in previous answers, that doesn't compile. But this compiles and works correctly (with my compiler):
person.GetNameAndAddr(name,
const_cast<string &>(static_cast<const string &>(string())));
This just shows that you can use casting to lie to the compiler. Obviously, it would be much cleaner to declare and pass an unused automatic variable:
string name;
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
This technique does introduce an unneeded local variable into the method's scope. If for some reason you want to prevent it from being used later in the method, e.g., to avoid confusion or error, you can hide it in a local block:
string name;
{
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
}
-- Chris
Why would you ever want X& x = getx();? Just use X x = getx(); and rely on RVO.
The evil workaround involves the 'mutable' keyword. Actually being evil is left as an exercise for the reader. Or see here: http://www.ddj.com/cpp/184403758
Excellent question, and here's my attempt at a more concise answer (since a lot of useful info is in comments and hard to dig out in the noise.)
Any reference bound directly to a temporary will extend its life [12.2.5]. On the other hand, a reference initialized with another reference will not (even if it's ultimately the same temporary). That makes sense (the compiler doesn't know what that reference ultimately refers to).
But this whole idea is extremely confusing. E.g. const X &x = X(); will make the temporary last as long as the x reference, but const X &x = X().ref(); will NOT (who knows what ref() actually returned). In the latter case, the destructor for X gets called at the end of this line. (This is observable with a non-trivial destructor.)
So it seems generally confusing and dangerous (why complicate the rules about object lifetimes?), but presumably there was a need at least for const references, so the standard does set this behavior for them.
[From sbi comment]: Note that the fact that binding it to a const reference enhances a
temporary's lifetimes is an exception that's been added deliberately
(TTBOMK in order to allow manual optimizations). There wasn't an
exception added for non-const references, because binding a temporary
to a non-const reference was seen to most likely be a programmer
error.
All temporaries do persist until the end of the full-expression. To make use of them, however, you need a trick like you have with ref(). That's legal. There doesn't seem to be a good reason for the extra hoop to jump through, except to remind the programmer that something unusual is going on (namely, a reference parameter whose modifications will be quickly lost).
[Another sbi comment] The reason Stroustrup gives (in D&E) for disallowing the binding of
rvalues to non-const references is that, if Alexey's g() would modify
the object (which you'd expect from a function taking a non-const
reference), it would modify an object that's going to die, so nobody
could get at the modified value anyway. He says that this, most
likely, is an error.
"It is clear that the temporary object is not constant in the sample above, because calls
to non-constant functions are permitted. For instance, ref() could modify the temporary
object."
In your example getX() does not return a const X so you are able to call ref() in much the same way as you could call X().ref(). You are returning a non const ref and so can call non const methods, what you can't do is assign the ref to a non const reference.
Along with SadSidos comment this makes your three points incorrect.
I have a scenario I would like to share where I wish I could do what Alexey is asking. In a Maya C++ plugin, I have to do the following shenanigan in order to get a value into a node attribute:
MFnDoubleArrayData myArrayData;
MObject myArrayObj = myArrayData.create(myArray);
MPlug myPlug = myNode.findPlug(attributeName);
myPlug.setValue(myArrayObj);
This is tedious to write, so I wrote the following helper functions:
MPlug operator | (MFnDependencyNode& node, MObject& attribute){
MStatus status;
MPlug returnValue = node.findPlug(attribute, &status);
return returnValue;
}
void operator << (MPlug& plug, MDoubleArray& doubleArray){
MStatus status;
MFnDoubleArrayData doubleArrayData;
MObject doubleArrayObject = doubleArrayData.create(doubleArray, &status);
status = plug.setValue(doubleArrayObject);
}
And now I can write the code from the beginning of the post as:
(myNode | attributeName) << myArray;
The problem is it doesn't compile outside of Visual C++, because it's trying to bind the temporary variable returned from the | operator to the MPlug reference of the << operator. I would like it to be a reference because this code is called many times and I'd rather not have MPlug being copied so much. I only need the temporary object to live until the end of the second function.
Well, this is my scenario. Just thought I'd show an example where one would like to do what Alexey describe. I welcome all critiques and suggestions!
Thanks.

Passing by reference from a return value gives me an error, when it does not if that same value is assigned to variable [duplicate]

Why is it not allowed to get non-const reference to a temporary object,
which function getx() returns? Clearly, this is prohibited by C++ Standard
but I am interested in the purpose of such restriction, not a reference to the standard.
struct X
{
X& ref() { return *this; }
};
X getx() { return X();}
void g(X & x) {}
int f()
{
const X& x = getx(); // OK
X& x = getx(); // error
X& x = getx().ref(); // OK
g(getx()); //error
g(getx().ref()); //OK
return 0;
}
It is clear that the lifetime of the object cannot be the cause, because
constant reference to an object is not prohibited by C++ Standard.
It is clear that the temporary object is not constant in the sample above, because calls to non-constant functions are permitted. For instance, ref() could modify the temporary object.
In addition, ref() allows you to fool the compiler and get a link to this temporary object and that solves our problem.
In addition:
They say "assigning a temporary object to the const reference extends the lifetime of this object" and " Nothing is said about non-const references though".
My additional question. Does following assignment extend the lifetime of temporary object?
X& x = getx().ref(); // OK
From this Visual C++ blog article about rvalue references:
... C++ doesn't want you to accidentally
modify temporaries, but directly
calling a non-const member function on
a modifiable rvalue is explicit, so
it's allowed ...
Basically, you shouldn't try to modify temporaries for the very reason that they are temporary objects and will die any moment now. The reason you are allowed to call non-const methods is that, well, you are welcome to do some "stupid" things as long as you know what you are doing and you are explicit about it (like, using reinterpret_cast). But if you bind a temporary to a non-const reference, you can keep passing it around "forever" just to have your manipulation of the object disappear, because somewhere along the way you completely forgot this was a temporary.
If I were you, I would rethink the design of my functions. Why is g() accepting reference, does it modify the parameter? If no, make it const reference, if yes, why do you try to pass temporary to it, don't you care it's a temporary you are modifying? Why is getx() returning temporary anyway? If you share with us your real scenario and what you are trying to accomplish, you may get some good suggestions on how to do it.
Going against the language and fooling the compiler rarely solves problems - usually it creates problems.
Edit: Addressing questions in comment:
1) `X& x = getx().ref(); // OK when will x die?` - I don't know and I don't care, because this is exactly what I mean by "going against the language". The language says "temporaries die at the end of the statement, unless they are bound to const reference, in which case they die when the reference goes out of scope". Applying that rule, it seems x is already dead at the beginning of the next statement, since it's not bound to const reference (the compiler doesn't know what ref() returns). This is just a guess however.
I stated the purpose clearly: you are not allowed to modify temporaries, because it just does not make sense (ignoring C++0x rvalue references). The question "then why am I allowed to call non-const members?" is a good one, but I don't have better answer than the one I already stated above.
Well, if I'm right about x in X& x = getx().ref(); dying at the end of the statement, the problems are obvious.
Anyway, based on your question and comments I don't think even these extra answers will satisfy you. Here is a final attempt/summary: The C++ committee decided it doesn't make sense to modify temporaries, therefore, they disallowed binding to non-const references. May be some compiler implementation or historic issues were also involved, I don't know. Then, some specific case emerged, and it was decided that against all odds, they will still allow direct modification through calling non-const method. But that's an exception - you are generally not allowed to modify temporaries. Yes, C++ is often that weird.
In your code getx() returns a temporary object, a so-called "rvalue". You can copy rvalues into objects (aka. variables) or bind them to to const references (which will extend their life-time until the end of the reference's life). You cannot bind rvalues to non-const references.
This was a deliberate design decision in order to prevent users from accidentally modifying an object that is going to die at the end of the expression:
g(getx()); // g() would modify an object without anyone being able to observe
If you want to do this, you will have to either make a local copy or of the object first or bind it to a const reference:
X x1 = getx();
const X& x2 = getx(); // extend lifetime of temporary to lifetime of const reference
g(x1); // fine
g(x2); // can't bind a const reference to a non-const reference
Note that the next C++ standard will include rvalue references. What you know as references is therefore becoming to be called "lvalue references". You will be allowed to bind rvalues to rvalue references and you can overload functions on "rvalue-ness":
void g(X&); // #1, takes an ordinary (lvalue) reference
void g(X&&); // #2, takes an rvalue reference
X x;
g(x); // calls #1
g(getx()); // calls #2
g(X()); // calls #2, too
The idea behind rvalue references is that, since these objects are going to die anyway, you can take advantage of that knowledge and implement what's called "move semantics", a certain kind of optimization:
class X {
X(X&& rhs)
: pimpl( rhs.pimpl ) // steal rhs' data...
{
rhs.pimpl = NULL; // ...and leave it empty, but deconstructible
}
data* pimpl; // you would use a smart ptr, of course
};
X x(getx()); // x will steal the rvalue's data, leaving the temporary object empty
What you are showing is that operator chaining is allowed.
X& x = getx().ref(); // OK
The expression is 'getx().ref();' and this is executed to completion before assignment to 'x'.
Note that getx() does not return a reference but a fully formed object into the local context. The object is temporary but it is not const, thus allowing you to call other methods to compute a value or have other side effects happen.
// It would allow things like this.
getPipeline().procInstr(1).procInstr(2).procInstr(3);
// or more commonly
std::cout << getManiplator() << 5;
Look at the end of this answer for a better example of this
You can not bind a temporary to a reference because doing so will generate a reference to an object that will be destroyed at the end of the expression thus leaving you with a dangling reference (which is untidy and the standard does not like untidy).
The value returned by ref() is a valid reference but the method does not pay any attention to the lifespan of the object it is returning (because it can not have that information within its context). You have basically just done the equivalent of:
x& = const_cast<x&>(getX());
The reason it is OK to do this with a const reference to a temporary object is that the standard extends the lifespan of the temporary to the lifespan of the reference so the temporary objects lifespan is extended beyond the end of the statement.
So the only remaining question is why does the standard not want to allow reference to temporaries to extend the life of the object beyond the end of the statement?
I believe it is because doing so would make the compiler very hard to get correct for temporary objects. It was done for const references to temporaries as this has limited usage and thus forced you to make a copy of the object to do anything useful but does provide some limited functionality.
Think of this situation:
int getI() { return 5;}
int x& = getI();
x++; // Note x is an alias to a variable. What variable are you updating.
Extending the lifespan of this temporary object is going to be very confusing.
While the following:
int const& y = getI();
Will give you code that it is intuitive to use and understand.
If you want to modify the value you should be returning the value to a variable. If you are trying to avoid the cost of copying the obejct back from the function (as it seems that the object is copy constructed back (technically it is)). Then don't bother the compiler is very good at 'Return Value Optimization'
Why is discussed in the C++ FAQ (boldfacing mine):
In C++, non-const references can bind to lvalues and const references can bind to lvalues or rvalues, but there is nothing that can bind to a non-const rvalue. That's to protect people from changing the values of temporaries that are destroyed before their new value can be used. For example:
void incr(int& a) { ++a; }
int i = 0;
incr(i); // i becomes 1
incr(0); // error: 0 is not an lvalue
If that incr(0) were allowed either some temporary that nobody ever saw would be incremented or - far worse - the value of 0 would become 1. The latter sounds silly, but there was actually a bug like that in early Fortran compilers that set aside a memory location to hold the value 0.
The main issue is that
g(getx()); //error
is a logical error: g is modifying the result of getx() but you don't have any chance to examine the modified object. If g didn't need to modify its parameter then it wouldn't have required an lvalue reference, it could have taken the parameter by value or by const reference.
const X& x = getx(); // OK
is valid because you sometimes need to reuse the result of an expression, and it's pretty clear that you're dealing with a temporary object.
However it is not possible to make
X& x = getx(); // error
valid without making g(getx()) valid, which is what the language designers were trying to avoid in the first place.
g(getx().ref()); //OK
is valid because methods only know about the const-ness of the this, they don't know if they are called on an lvalue or on an rvalue.
As always in C++, you have a workaround for this rule but you have to signal the compiler that you know what you're doing by being explicit:
g(const_cast<x&>(getX()));
Seems like the original question as to why this is not allowed has been answered clearly: "because it is most likely an error".
FWIW, I thought I'd show how to it could be done, even though I don't think it's a good technique.
The reason I sometimes want to pass a temporary to a method taking a non-const reference is to intentionally throw away a value returned by-reference that the calling method doesn't care about. Something like this:
// Assuming: void Person::GetNameAndAddr(std::string &name, std::string &addr);
string name;
person.GetNameAndAddr(name, string()); // don't care about addr
As explained in previous answers, that doesn't compile. But this compiles and works correctly (with my compiler):
person.GetNameAndAddr(name,
const_cast<string &>(static_cast<const string &>(string())));
This just shows that you can use casting to lie to the compiler. Obviously, it would be much cleaner to declare and pass an unused automatic variable:
string name;
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
This technique does introduce an unneeded local variable into the method's scope. If for some reason you want to prevent it from being used later in the method, e.g., to avoid confusion or error, you can hide it in a local block:
string name;
{
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr
}
-- Chris
Why would you ever want X& x = getx();? Just use X x = getx(); and rely on RVO.
The evil workaround involves the 'mutable' keyword. Actually being evil is left as an exercise for the reader. Or see here: http://www.ddj.com/cpp/184403758
Excellent question, and here's my attempt at a more concise answer (since a lot of useful info is in comments and hard to dig out in the noise.)
Any reference bound directly to a temporary will extend its life [12.2.5]. On the other hand, a reference initialized with another reference will not (even if it's ultimately the same temporary). That makes sense (the compiler doesn't know what that reference ultimately refers to).
But this whole idea is extremely confusing. E.g. const X &x = X(); will make the temporary last as long as the x reference, but const X &x = X().ref(); will NOT (who knows what ref() actually returned). In the latter case, the destructor for X gets called at the end of this line. (This is observable with a non-trivial destructor.)
So it seems generally confusing and dangerous (why complicate the rules about object lifetimes?), but presumably there was a need at least for const references, so the standard does set this behavior for them.
[From sbi comment]: Note that the fact that binding it to a const reference enhances a
temporary's lifetimes is an exception that's been added deliberately
(TTBOMK in order to allow manual optimizations). There wasn't an
exception added for non-const references, because binding a temporary
to a non-const reference was seen to most likely be a programmer
error.
All temporaries do persist until the end of the full-expression. To make use of them, however, you need a trick like you have with ref(). That's legal. There doesn't seem to be a good reason for the extra hoop to jump through, except to remind the programmer that something unusual is going on (namely, a reference parameter whose modifications will be quickly lost).
[Another sbi comment] The reason Stroustrup gives (in D&E) for disallowing the binding of
rvalues to non-const references is that, if Alexey's g() would modify
the object (which you'd expect from a function taking a non-const
reference), it would modify an object that's going to die, so nobody
could get at the modified value anyway. He says that this, most
likely, is an error.
"It is clear that the temporary object is not constant in the sample above, because calls
to non-constant functions are permitted. For instance, ref() could modify the temporary
object."
In your example getX() does not return a const X so you are able to call ref() in much the same way as you could call X().ref(). You are returning a non const ref and so can call non const methods, what you can't do is assign the ref to a non const reference.
Along with SadSidos comment this makes your three points incorrect.
I have a scenario I would like to share where I wish I could do what Alexey is asking. In a Maya C++ plugin, I have to do the following shenanigan in order to get a value into a node attribute:
MFnDoubleArrayData myArrayData;
MObject myArrayObj = myArrayData.create(myArray);
MPlug myPlug = myNode.findPlug(attributeName);
myPlug.setValue(myArrayObj);
This is tedious to write, so I wrote the following helper functions:
MPlug operator | (MFnDependencyNode& node, MObject& attribute){
MStatus status;
MPlug returnValue = node.findPlug(attribute, &status);
return returnValue;
}
void operator << (MPlug& plug, MDoubleArray& doubleArray){
MStatus status;
MFnDoubleArrayData doubleArrayData;
MObject doubleArrayObject = doubleArrayData.create(doubleArray, &status);
status = plug.setValue(doubleArrayObject);
}
And now I can write the code from the beginning of the post as:
(myNode | attributeName) << myArray;
The problem is it doesn't compile outside of Visual C++, because it's trying to bind the temporary variable returned from the | operator to the MPlug reference of the << operator. I would like it to be a reference because this code is called many times and I'd rather not have MPlug being copied so much. I only need the temporary object to live until the end of the second function.
Well, this is my scenario. Just thought I'd show an example where one would like to do what Alexey describe. I welcome all critiques and suggestions!
Thanks.

Are all temporaries rvalues in C++?

I have been coding in C++ for past few years. But there is one question that I have not been able to figure out. I want to ask, are all temporaries in C++, rvalues?
If no, can anyone provide me an example where temporary produced in the code is an lvalue?
No.
The C++ language specification never makes such a straightforward assertion as the one you are asking about. It doesn't say anywhere in the language standard that "all temporary objects are rvalues". Moreover, the question itself is a bit of misnomer, since the property of being an rvalue in the C++ language is not a property of an object, but rather a property of an expression (i.e. a property of its result). This is actually how it is defined in the language specification: for different kinds of expressions it says when the result is an lvalue and when it is an rvalue. Among other things, this actually means that a temporary object can be accessed as an rvalue as well as an lvalue, depending on the specific form of expression that is used to perform the access.
For example, the result of literal 2 + 3 expression is obviously an rvalue, a temporary of type int. We cannot apply the unary & to it since unary & requires an lvalue as its operand
&(2 + 3); // ERROR, lvalue required
However, as we all know, a constant reference can be attached to a temporary object, as in
const int &ri = 2 + 3;
In this case the reference is attached to the temporary, extending the lifetime of the latter. Obviously, once it is done, we have access to that very same temporary as an lvalue ri, since references are always lvalues. For example, we can easily and legally apply the unary & to the reference and obtain a pointer to the temporary
const int *pi = &ri;
with that pointer remaining perfectly valid as long as the temporary persists.
Another obvious example of lvalue access to a temporary object is when we access a temporary object of class type through its this pointer. The result of *this is an lvalue (as is always the case with the result of unary * applied to a data pointer), yet it doesn't change the fact that the actual object might easily be a temporary. For a given class type T, expression T() is an rvalue, as explicitly stated in the language standard, yet the temporary object accessed through *T().get_this() expression (with the obvious implementation of T::get_this()) is an lvalue. Unlike the previous example, this method allows you to immediately obtain a non-const-qualified lvalue, which refers to a temporary object.
So, once again, the very same temporary object might easily be "seen" as an rvalue or as an lvalue depending on what kind of expression (what kind of access path) you use to "look" at that object.
Prasoon Saurav already linked a very good clc++ thread. In there, James Kanze explains why the question doesn't really make sense. It boils down to:
rvalue-ness is a (boolean) property of expressions - each expression is either an lvalue or an rvalue
temporaries are not expressions
For that reason, the question doesn't make sense.
A good example is the following code:
int main() {
const int& ri = 4;
std::cout << ri << std::endl;
}
The temporary int with value 4 is not an expression. The expression ri that's printed is not a temporary. It's an lvalue, and refers to a temporary.
well, that array operator returns a reference, any function that returns a reference could be considered to do the same thing? all references are const, while they can be lvalues, they modify what they reference, not the reference itself. same is true for the *operator,
*(a temp pointer) = val;
I swear I used to use some compiler that would pass temp values to any function that took a reference,
so you could go:
int Afunc()
{
return 5;
}
int anotherFunc(int & b)
{
b = 34;
}
anotherFunc(Afunc());
can't find one that lets you do that now though, the reference has to be const in order to allow passing of temp values.
int anotherFunc(const int & b);
anyway, references can be lvalues and temporary, the trick being the reference it's self is not modified, only what it references.
if you count the-> operator as an operator, then temporary pointers can be lvalues, but the same condition applies, its not the temp pointer that would be changed, but the thing that it points to.
An array indexing operation is both a temporary and an lvalue, something like a[10] = 1 is an example of what you're looking for; the lvalue is a temporary, calculated pointer.
Short answer: yes, but I'm not going to quote the standard, because proving the point would require addressing every kind of temporary there is. By definition a temporary has a lifetime of one statement, so assigning things to one would be poor style at best.
Interesting answer: Copy elision can make (often makes) a temporary object identical with an lvalue object. For example,
MyClass blah = MyClass( 3 ); // temporary likely to be optimized out
or
return MyClass( 3 ); // likely to directly initialize object in caller's frame
Edit: as for the question of whether there is any temporary object in those cases, ยง12.8/15 mentions
the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy
which would indicate that there is a temporary object which may be identical with an lvalue.
It depends on what you consider a temporary variable is. You can write something like
#include <stdio.h>
int main()
{
char carray[10];
char *c=carray+1;
*(c+2+4) = 9;
printf("%d\n",carray[7]);
return 0;
}
This runs in VisualStudios and GCC. You can run the code in codepad
I consider (c+2+4) a rvalue although i want to assign to it. When i dereference it, it would become an lvalue. So yes all temporaries are rvalues. But you can make rvalues (thus a temporary) into an lvalue by dereferencing it
If no, can anyone provide me an example where temporary produced in the code is an lvalue?
The following code binds a constant reference to a temporary object of type const float created by the compiler:
int i;
const float &cfr = i;
The behaviour is "as if":
int i;
const float __tmp_cfr = i; // introduced by the compiler
const float &cfr = __tmp_cfr;