5

I have been having some confusion on the reference in C++, so I did a little experiment with the following function

std::vector<float> & fun(std::vector<float> & x) {
    return x;
}

Then I call the function using the following two ways:

std::vector<float> x(10000);
std::vector<float> result1 = fun(x);
std::vector<float> & result2 = fun(x);

Now the variable result2 is indeed a reference of x, but result1 seems to be a copy of x instead of a reference. So here I am confused:

Why can I declare a non-reference variable to be the return value of a function that returns a reference?

Does C++ changes my returned reference to a non-reference variable because my declaration of result1 is not a reference?

2
  • Because the assignment operator, like the copy constructor, for std::vector accepts a (const) reference. That operator does a deep copy. Commented Jul 31, 2018 at 2:26
  • I think in this case it is the copy ctor that invoked, not the assigment operator. assigment is only between already existing objects. Commented Nov 17, 2020 at 22:45

3 Answers 3

12

Since fun(x) simply accepts a reference to x and returns it, your code (on the left) is equivalent to the code on the right:

a std::vector<float> x(10000);          a std::vector<float> x(10000);

std::vector<float> result1 = fun(x);    std::vector<float> result1 = x;
std::vector<float> &result2 = fun(x);   std::vector<float> &result2 = x;

In other words, result1 becomes a copy of x, while result2 becomes a reference to x. That means result1 is distinct from x, while result2 and x refer to the same underlying data.

It's really no different to:

int a = 42;
int b = a;
int &c = a;

At that point, b is an independent copy that, if changed, will not affect the other two variables. However, since a and c refer to the same underlying data, changing one will affect the other.

Sign up to request clarification or add additional context in comments.

Comments

5

That's basically the same as

std::vector<float> x(10000);
std::vector<float> & result2 = x;
std::vector<float> result1 = result2;

The language allows it since result2 is a reference of x, each mention of result2 is the same as x. You could see the reference as being an alias, result2 is an alias of x.

Comments

1

There's no real change happening.

What happens is that a reference refers to something, and when you use the reference in an expression, you (usually) get what it refers to. So, if I have something like:

int x = 1;
int &rx = x;

std::cout << rx;

What gets printed out is the value of x--the reference gets dereferenced to get the value, and that's what gets printed out. Likewise, if I had something like:

int x = 1;
int y = 2;
int rx = x;
int ry = y;
int z = rx + ry;

...the compiler is going to dereference rx and ry to get the values of x and y. Then it adds those together, and assigns the result to z.

Summary

A reference is an alias for some object. Under most circumstances (essentially anything other than initializing another reference) using the reference in an expression uses the object that the reference refers to, not the reference itself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.