53

Does dereferencing a pointer and passing that to a function which takes its argument by reference create a copy of the object?

wrongusername
  • 18,564
  • 40
  • 130
  • 214
  • 4
    Re: the title. If dereferencing a pointer made a copy of the object, wouldn't it be impossible to ever use the object?! – visitor Dec 14 '10 at 11:03
  • @visitor It would still be possible, right? For instance, `this->doSomething()` uses the original object. But `(*this).doSomething()` would make a copy of the object and does something on it. – Harsh Aug 16 '22 at 19:01

4 Answers4

46

In this case the value at the pointer is copied (though this is not necessarily the case as the optimiser may optimise it out).

int val = *pPtr;

In this case however no copy will take place:

int& rVal = *pPtr;

The reason no copy takes place is because a reference is not a machine code level construct. It is a higher level construct and thus is something the compiler uses internally rather than generating specific code for it.

The same, obviously, goes for function parameters.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • 11
    It is not the pointer that's copied in the first case. It's the value it points to that is copied. In second case, the pointer is copied (logically) and the value isn't. – Sergei Tachenov Dec 14 '10 at 07:56
  • 2
    I wrote a simple test program to verify the answers for myself, hopefully this helps some http://codepad.org/XDqahndf – RishiD Feb 22 '13 at 21:27
  • So with the rVal we can still read what is at that mem location without a copy, right? – Dominic May 31 '21 at 13:50
  • Exactly. Of course if the original value goes out of scope you're now reading random memory ... – Goz Jun 04 '21 at 08:32
8

In the simple case, no. There are more complicated cases, though:

void foo(float const& arg);
int * p = new int(7);
foo(*p);

Here, a temporary object is created, because the type of the dereferenced pointer (int) does not match the base type of the function parameter (float). A conversion sequence exists, and the converted temporary can be bound to arg since that's a const reference.

MSalters
  • 173,980
  • 10
  • 155
  • 350
4

Hopefully it does not : it would if the called function takes its argument by value.

Furthermore, that's the expected behavior of a reference :

void inc(int &i) { ++i; }

int main()
{
    int i = 0;
    int *j = &i;
    inc(*j);
    std::cout << i << std::endl;
}

This code is expected to print 1 because inc takes its argument by reference. Had a copy been made upon inc call, the code would print 0.

icecrime
  • 74,451
  • 13
  • 99
  • 111
3

No. A reference is more or less just like a pointer with different notation and the restriction that there is no null reference. But like a pointer it contains just the address of an object.

hmuelner
  • 8,093
  • 1
  • 28
  • 39
  • 2
    "But like a pointer it contains just the address of an object." Reference does not have an existence of its own.It is just an alias to the object it was initialized to. So saying "it contains" address will be wrong. The reference just points to the same address as the original object, it does not contain that address. – Alok Save Dec 14 '10 at 07:58
  • Why not? How can it point somewhere and not contain the address? It does contain it, only you can't access the address it contains because it is automatically dereferenced any time you access it. – Sergei Tachenov Dec 14 '10 at 08:50
  • @Sergey Tachenov: The compiler has to create the fiction that it is an alias, and can assume it. This means that depending on the use, the compiler can create an *internal* pointer and automatically dereference it on use, or in some cases it can just refer to the original object altogether. In most cases it has to resort to pointers, but at the end of the day, you are better off thinking in abstract terms: references are *aliases* regardless of how they are implemented. – David Rodríguez - dribeas Dec 14 '10 at 09:02
  • In some situations it is better to thing of references as aliases to other variables. But if you have references parameters or variables that "contain" references it is hard to imagine them this way. This example outputs 8: #include class test1 { public: test1(int& a, int&b) : a_(a), b_(b) {}; int& a_; int& b_; }; int main() { std::cout << sizeof(test1) << "\n"; } – hmuelner Dec 14 '10 at 09:36