Home > Back-end >  did const int& pass a reference or a copy
did const int& pass a reference or a copy

Time:12-16

For example,

void func(const int& a);
int main()
{
    int b=1;
    func(b*2);
}

If the const int& will pass a reference, how can b*2 be a reference?

So it means it only pass a copy of b*2 to func()?

But if so, did func(b) really pass a reference of b?

Am I right?

CodePudding user response:

The & in this example indeed does denote a reference, so it has to refer to an actual object.

b*2 creates a temporary int object in memory (an rvalue). When the statement func(b*2); is finished (ie, when the ; is reached), that temporary will be destroyed.

While the statement func(b*2) is still running, the temporary still exists. A reference-to-const can bind to a temporary/rvalue object, which is why the code compiles and runs fine.

However, a non-const reference cannot bind to a temporary/rvalue, only to a named variable (an lvalue). So, if you were to drop the const (ie void func(int& a)) then the statement func(b*2) would no longer compile.

CodePudding user response:

It's simple:

int b = 1;

Here, b is an lvalue. so when you write func( b ) then you are passing an lvalue to the func. And it works since func can take an lvalue by reference.

But:

func( b*2 );

Here, b*2 is a prvalue (which is under the rvalue category) and when you write func( b*2 ); then you are passing an rvalue to the func. And it works since void func(const int& a); has a const lvalue reference parameter and const lvalue references can bind to rvalues.

Now if you rewrite your function like this void func(const int&& a); so that it only takes rvalues as its argument (notice the &&), then func( b*2 ) will still compile but func( b ) won't because b is an lvalue and lvalues can not be moved unless you cast it to an xvalue (which is also under the rvalue and glvalue category) like this:

func( std::move( b ) )

In short, std::move casts an lvalue to an xvalue to tell the compiler that it is temporary and thus can be moved from.

For the sake of completeness:

In C 11, expressions that:

  • have identity and cannot be moved from are called lvalue expressions;
  • have identity and can be moved from are called xvalue expressions;
  • do not have identity and can be moved from are called prvalue ("pure rvalue") expressions;
  • do not have identity and cannot be moved from are not used.

The expressions that have identity are called "glvalue expressions" (glvalue stands for "generalized lvalue"). Both lvalues and xvalues are glvalue expressions.

The expressions that can be moved from are called "rvalue expressions". Both prvalues and xvalues are rvalue expressions.

It's as simple as this!

Check value category for more info.

  • Related