1

I'm currently learning C++, and am a bit confused about the concept of returning a reference from a method. Consider the following toy example:

#include <iostream>
#include <vector>

class IntHolder {

private:

    std::vector<int> d_values;

public:

    IntHolder() {
        d_values.push_back(1);
        d_values.push_back(2);
        d_values.push_back(3);
    }

    std::vector<int> &values() {
        return d_values;
    }

};

int main(int argc, char **argv) {
    IntHolder h;
    std::vector<int> ret_val = h.values();
    std::cout << ret_val.size() << std::endl;

    ret_val.push_back(4);
    ret_val.push_back(5);

    std::cout << h.values().size() << std::endl;

    return 0;
}

This prints the following to the standard output:

3
3

Since we are returning a reference to d_values, shouldn't the object returned be the same that is stored in the instance of IntHolder, and thus when calling h.values() again, we should see a size of 5?

Since this is not the case, what is the difference between returning a reference to an object or a copy of the object? Is there a difference when you are returning from a method?

Ryan
  • 7,621
  • 5
  • 18
  • 31

3 Answers3

3

You are returning a reference from the values function, but you are not assigning that returned object to a reference variable. Instead, you are making a copy of it because you are assigning it to a new std::vector<int> named ret_val.

You want to modify your code like so, in order to capture the returned reference:

std::vector<int>& ret_val = h.values();

Or perhaps simply:

auto& ret_val = h.values();
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
1

Your method is returning a reference, but you are then assigning the result to another vector, causing a copy. To fix this, change your ret_val definition to:

std::vector<int> & ret_val = h.values();
md5i
  • 3,018
  • 1
  • 18
  • 32
0

If you return a reference, you return the same object and you are not creating a copy. Basically it seems that it is just as you did expect it:

std::cout << h.values().size() << std::endl;
h.values().push_back(4);
h.values().push_back(5);
std::cout << h.values().size() << std::endl;

Would return

3
5

The misstage is another one. Let's look at

std::vector<int> ret_val = h.values();

You discovered that ret_val is a copy of h.d_values while h.values() is returning a reference to it. We could rewrite your code above as follows:

std::vector<int> &ret_ref = h.values(); // object returned by `h.values()`
std::vector<int>  ret_val = ret_ref;

If you are calling ret_ref.push_back(4), h.d_values would change. But ret_val is a copy of the returned object and will not affect h.d_values.

JojOatXGME
  • 3,023
  • 2
  • 25
  • 41