0

my code:


#include <iostream>
using namespace std;

int a = 100;

int func();

int main()
{
    int c = 10;
    int & d = c;
//  int & b = func();
    int & b = a;
    cout << b << endl;
    return 0;
}

int func()
{
    return a;
}

if I open the commment line. My g++ compiler will prompt error cannot bind non-const lvalue referrence of type int& to an rvalue of type int. This is so strange. This statement is so similar to its next line int & b = a. Why its next line can work well and do not prompt the same error.

And another strange is after I modify my func definition which I modify its return type form int to int & the g++ will not prompt the error.

I usually use java and I just learn c++ last week. I need some experts help.

Melvin Levett
  • 171
  • 2
  • 11

2 Answers2

3

This statement is so similar to its next line int & b = a. Why its next line can work well and do not prompt the same error.

The next line works because a is an lvalue. Lvalues can be bound to lvalue references (of compatible type). Rvalues cannot be bound to lvalue references to non-const types.

And another strange is after I modify my func definition which I modify its return type form int to int & the g++ will not prompt the error.

This is because a call to function that returns an lvalue reference is also an lvalue expression.

eerorika
  • 181,943
  • 10
  • 144
  • 256
  • OK. According your explanation, func returns `int` stands for it return rvalue, no matter what it returns in fact, in my code it return a global var. – Melvin Levett Oct 28 '20 at 05:05
  • 1
    @MelvinLevett Yes. A call to a function that returns an object is always a prvalue. – eerorika Oct 28 '20 at 05:06
  • And what puzzles me is when I modify my func return type like what I said last. Its siganature is `int &` but it just return var `a` in fact (which is `int` not `int &`) and the g++ will not prompt type imcompatitable. – Melvin Levett Oct 28 '20 at 05:08
  • 1
    @MelvinLevett It returns a *temporary copy* of the global value. C++ makes much greater use of Value semantics than Java does. See [What's the difference between passing by reference vs. passing by value?](https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value). You're going to have to ignore a lot of your Java language knowledge when working with C++. – user4581301 Oct 28 '20 at 05:09
  • 2
    @MelvinLevett `a` expression is an lvalue of type `int`. Such value can be bound to a reference also when returning that reference, exactly as it can be bound when initialising a reference variable. – eerorika Oct 28 '20 at 05:11
  • @errorika I have known a little from your explanation. I need more reading. thanks – Melvin Levett Oct 28 '20 at 05:14
1
int & b = func();

and

 int & b = a;

define a lvalue references.

a is an lvalue. b can refer to it.

func() does not return the global variable a. It returns a temporary copy of a, a prvalue. This result is so short lived, it expires at the end of the line, that taking a reference to it is pointless. The returned value will be invalid before you can use the reference, so the compiler's protecting you from a runtime error.

But if you make a const reference,

const int & b = func();

the compiler will perform some deep magic to preserve the returned value

Handy reading: What are rvalues, lvalues, xvalues, glvalues, and prvalues?

user4581301
  • 29,019
  • 5
  • 26
  • 45