4

Facts that I have known:

  1. There are three types of variables in C++: variables, pointers and references.
  2. Variables is kinda label for the memory that stores the actual data.
  3. Pointers stored the address of the variables.
  4. References are alias for the variables.

My questions:

  1. By observation, the use of variables names and references is exchangeable. Is that true?
  2. What is the difference between passing a variable name as parameter and passing a reference? e.g.,

    void func(int a); vs void func2(int& b);

Thanks a million!

user3367047
  • 323
  • 1
  • 4
  • 9
  • No, the names are not quite interchangable. For example, http://coliru.stacked-crooked.com/a/57a496c47639304b – chris Mar 05 '14 at 22:54

3 Answers3

15

Here is a way to understand the difference:

  • Objects that can change state are also called "variables".
  • Pointers are objects (variable or not). They have a state.
  • References are "nicknames". They don't have a state, but expose the state of the refereed object (which is why you can't re-assign a reference, it's not an actual object).

Now, in some cases references might be implemented as pointers, but from the language point of view, references are just not pointers, they really are additional names for an object already existing.

As pointers are objects, and have a state, passing pointers to functions will copy that state, the pointer's state, not the pointee's state. However, references have no state, so if you pass a reference to a function, it's the refereed object that you pass (by copy).

By observation, the use of variables names and references is exchangeable. Is that true?

"References are nickname" is the best way to understand references.

What is the difference between passing a variable name as parameter and passing a reference? e.g.,

void func(int a); vs void func2(int& b);

The first implementation ask for a copy of the object passed. That is, internally func() can do anything to a, without changing the object that was passed to func() because internally func() made a copy of that object and manipulates the copy, not the original.

The second implementation ask for "a nickname for an object already existing". First, the object have to exist and if passed, a nickname for it will be created inside the function. That nickname, the reference b, is still a nickname for the original object. This mean that any manipulation done to b will affect the original object passed to func2().

  • func() signature says "I need this data but I will not modify the original object passed.".
  • func2() signature says "I need an object that I WILL certainly modify, pass it so that I can modify it".

Bonus stage:

At this point, if you don't know yet about const, that might be useful: in function signatures const is used with references to specify the arguments that are "read-only".

Let me clarify:

void func3( const int& b);

Here func3 says: "I need to access to an object, but really I will not make a copy of it. However I guarantee that I will not change that object".

So, why would we need that? Because some objects are expensive to copy. int is cheap to copy so most people will just pass it and func() and func3() are basically equivalent (depends on implementation but generally true).

If however we want to pass, says, a very big object, like a data buffer, we really don't want to copy it again and again just to apply some algorithms. So we do want to pass it by reference. However, depending on the function, sometime you want to extract information and work with it, so you only need "read-only" access to the argument. In this case you use const Object&. However, if you need to apply the algorithm to the object passed, you need to be able to modify it, which you could call "write-access". In this case, you need to use a normal reference. Asking for a copy basically mean that you want to manipulate an object that is the same state than the passed object, but is not the passed object.

To summarize:

  • func( T object ) : I want to have a copy of an object of type T;
  • func( T& object ) : I want to have "write-access" to an object of type T - assume that I will modify that object!;
  • func( const T& object ) or func( T const & object ) // which are the same : I want to read the state of an object, but I guarantee you that I will not modify it, I want "read-only" access.

Actually, the "read-only" guarantee could be violated using const_cast<> but that's a different story and it's only used in some very very very narrow cases.

Last thing you need to know is that if you have a member function, then you can do:

class K{
public:
     void func() const; // see the const?
};

In this specific case, what you say is that inside the function, which is basically equivalent to: void func( const K* this );

In this case you can see that this is a pointer but it's pointing to a const object. This mean that func() guarantee that the object it is member of (this) is never modified through this function (except some specific cases, see mutable keyword, another long story).

Klaim
  • 67,274
  • 36
  • 133
  • 188
2

Let's say you have these two functions:

void addone(int a) {
   a += 1;
}

void addone_bis(int &a) {
  a += 1;
}

If you call the first function in your main function, the value will only change in the function addone and not in the main, whereas if you call addone_bis the value of a will also be changed in the main function.

int main() {
   int test_a = 10;
   int test_b = 11;

   addone(test_a);
   // test_a still equals 10.

   addone_bis(test_b);
   // test_b now equals 12.

}

Did I correctly answer to your question?

Aliou
  • 1,065
  • 11
  • 17
1

Your first example is what is known as PASSING BY VALUE. What this means is that a copy of the ACTUAL value is passed into the routine.

When passing in the way of your second example, this is what is known as PASSING BY REFERENCE. A reference is ESSENTIALLY a passing of the variable into the routine such that its ACTUAL VALUE can be modified by the called routine without DE-REFERENCING.

trumpetlicks
  • 7,033
  • 2
  • 19
  • 33