Why not non-const reference to temporary objects?

2019-09-14 18:41发布

问题:

C++ allows assignment of temporary objects only to const reference. It wont allow assignement of temporary objects to reference.

For example:

String& a = String("test");         // Error
const String& a = String("test");   // Ok

Everywhere I google for this result, i only see the following answers

  1. Modifying temporary objects would cause unidentifiable problems
  2. Modifying temporary objects is dangerous
  3. At some point of time, you will forget it is a temporary variable

It's been said, temporary objects vanishes after the statement. So you should not modify it.

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? The possible cases, where a right can occur, could also involve the read too.

Then why its been blocking write alone and allowing read?

Please give me a solid c++ code explanation.

Please dont deviate the question by pointing some alternatives. Please give me solid answer with code why const int & is allowed and int & is not allowed for temporary objects.

One says && is there.. My question different.. ANother say,changing will not reflect.. Changing will not reflect even when it is const int & too. Eg: double a; Const int & i = a; a++; will not affect i..

回答1:

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?



回答2:

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.



回答3:

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.



回答4:

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.