Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When and why do I get a copy when initializing a reference?

Tags:

c++

reference

There are cases when I want a reference to an object but instead I get a copy. Here is an example:

  std::pair<const std::string, int> foo("hello", 5);
  const std::pair<std::string, int> & bar = foo;

  std::cout << "foo: " << foo.first << " " << foo.second << std::endl;
  std::cout << "bar: " << bar.first << " " << bar.second << std::endl;
  foo.second = 7;
  std::cout << "foo: " << foo.first << " " << foo.second << std::endl;
  std::cout << "bar: " << bar.first << " " << bar.second << std::endl;

This produces:

foo: hello 5
bar: hello 5
foo: hello 7
bar: hello 5

So apparently a copy of foo has been created while the syntax suggests (to me at least) that the programmer wanted a reference to it. This violates the principle that a reference should be an alias to something. It would be great if somebody could explain what is going on and why.

(Note: I came across this here)

like image 994
Sarien Avatar asked Jan 26 '15 13:01

Sarien


1 Answers

The underlying types of foo and bar are different, so a temporary is created using an implicit conversion from the type on the RHS to the one on the LHS*. The C++ standard allows for a const reference to bind to a temporary and extend its lifetime.

The const reference bar binds to that temporary, which is a distinct object from foo.

If you were to use the same types, you'd get the result you expect:

std::pair<const std::string, int> foo("hello", 5);
const std::pair<const std::string, int> & bar = foo;

or

std::pair<std::string, int> foo("hello", 5);
const std::pair<std::string, int> & bar = foo;

would yield

foo: hello 5
bar: hello 5
foo: hello 7
bar: hello 7

*std::pair has a template constructor that allows this implicit conversion from one type of pair to another.

like image 114
juanchopanza Avatar answered Oct 25 '22 06:10

juanchopanza