Why not non-const reference to temporary objects? [duplicate]
The original case for not allowing references to temporaries was for function parameters. Suppose this was allowed:
void inc(double& x)
{ x += 0.1; }
int i = 0;
inc(i);
Why isn't i
changed?
If C++, is so keen in blocking modifying the temporary objects, it should have blocked reading the temporary objects right? If the temporary object is vanished, then there is no point in reading contents from there right?
No, reading the object is perfectly sensible. Just because it's going to vanish in the future doesn't mean reading the data now is pointless.
open_file(std::string("foo.txt"));
std::string("foo.txt")
is a temporary which will stop existing after the call to open_file()
but the data it contains while it does exist matters very much.
The rational for not allowing temporaries bind to non-const references isn't actually some fundamental problem with writing to temporaries. In fact in many places C++ is perfectly happy to allow temporaries to be modified:
std::string("foo") = "bar";
It's just that the designers felt that it would cause a sufficient number of problems (probably due to the common idiom of 'out parameters') without enabling anything of similar value, so they simply made a design decision to prohibit temporaries binding to non-const references.
With rvalue references now you can do exactly what was prohibited before:
void foo(int &&output) {
output = 1;
}
foo(2);
This works fine, it's just not very useful.
If you have a temporary object that's very expensive to copy, you may prefer to take a const&
to that object (say a function return) rather than copying it into another variable to use later. Taking a constant reference to a temporary extends the life of that temporary to as long as the reference lives, allowing you to access any readable state.
Writing is disallowed because as soon as you want to mutate a variable you may as well have a real instance rather than a temporary that's aliased only as a non-const reference.
There is a logical reason to this. Think, what actually you want in this line:
String& a = String("test"); // Error
You want a reference. A reference relates to the object it references to. Like an address of the object (although references are not addresses, it makes the explanation clearer this way). You actually try to get something like an address of String("test")
. But that object will vanish right on the next line, so what's the point of its address, if the object it points to doesn't exist? a
now points to something meaningless...
Regarding your second question, what's the point of allowing for temporary objects alltogether, well, there is nothing wrong with that. Consider for example, the case where you want to pass a String
object to a function, which returns, say, a modified string corresponding to that String. Let's call the function DoubleString, so instead of doing
String s("hello ");
String s2 = DoubleString(s);
You can use a shorter, more convenient form
String s2 = DoubleString(String("hello "));
See, the temporary object String("hello ")
survives the entire line of code, which means it is intact when sent to DoubleString
and after it. It is destroyed only when the entire line has finished.