简体   繁体   中英

Why does the const qualifier allow temporary objects or rvalues?

Here is a simple function which sums two integers. Now the parameters here are integer references.

#include <iostream>
#include <cstdlib>

using namespace std;

int sum (int &a, int &b)
{
  return(a + b);
}

int main()

  int a = 23, b = 34;

  cout << sum(a, b) << endl; // this works

  cout<< sum(2, 5) <<endl; // as expected, this does not work; compilation fails

  return(0);
}

So it does not work with sum(2, 5) which is understood because there cannot be binding between rvalues (here 2 and 5) and reference variables in the function 'sum'. But it works if the function definition is modified to

int sum (const int& a, const int& b)
{
    return (a + b);
}

So what change does the const qualifier make that now even refernce variables can bind to rvalues?

Lvalues represent objects and rvalues represent values (loosely speaking). Binding an rvalue to a non- const lvalue reference would allow you to modify the value - what exactly does that mean? If you had written a = 3 in your function, you'd be attempting to modify the value 2 to make it 3 . That just doesn't make sense conceptually. However, const lvalue references do not allow modification and only allow you to observe a value, which does make sense.

However, there often are object behind rvalue expressions and it can be useful to modify those objects (such as to steal its resources). This is precisely why the rvalue reference was introduced.

Rvalues and temporaries behave like read only references. So binding them to a non const reference would violate this nature. Declaring a reference as const you are fullfilling the read only contract.

On your particular case, the ints 23 etc are called numerals and are inherently constants (have a fixed value). In C++ modifying a constant is undefined behaviour, so your numerals only bind to const references.

In sum(2, 5) 2 and 5 are rvalues.

An rvalue cannot bind to a non-const lvalue reference like the one in your first sum int& , you need const T& so later function works for both.

In C++11 you can change it to following to make it always work, regardless what you pass it:

int sum (int &&a, int &&b)
{
    return(a + b);
}

It will give you a non-const reference to 2 and 5 (ie you can modify the values inside the sum(2, 5) call though a and b ). This is safe and will not give any weird side effects, even if it had been temporary objects instead of primitives (like string("foo") ) because the arguments to sum() do not have a name. That they don't have a name makes you unable to observe the modification in any way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM