Understanding Pointers and References

I have been doing C++ for quite a while and still cant seem to get a grasp of how pointers and references, using and when to use them.

Below is a basic polymorphism example I've been studying which has the &, -> and * symbols I have a slight idea of what each does but I do not know the context of when to use each.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Animal
{
public:
	virtual void MakeNoise()
	{
		std::cout << "Animal Noise." << std::endl;
	}
};

class Dog : public Animal
{
public:
	void MakeNoise() override
	{
		std::cout << "Woof" << std::endl;
	}
};

class Cat : public Animal
{
public:
	void MakeNoise() override
	{
		std::cout << "Meow" << std::endl;
	}
};

void Stroke(Animal* animal)
{
	animal->MakeNoise();
}

int main()
{
	Dog dog;
	Cat cat;
	Stroke(&dog);
	Stroke(&cat);
    return 0;
}


Another way of running the exact same code would be

1
2
3
4
5
6
7
8
9
10
11
12
13
void Stroke(Animal& animal)
{
	animal->MakeNoise();
}

int main()
{
	Dog dog;
	Cat cat;
	Stroke(dog);
	Stroke(cat);
    return 0;
}


And again I do not understand why or how this works. I've searched plenty of resources in an attempt to understand how and when to use a -> instead of a .

And when to use the * or &.

I would appreciate a simple to follow explanation
Last edited on
The difference is, a reference is always bound to an object, whereas a pointer can refer to a object or nothing (null).

Both are forms of indirection, and often can be used interchangeably. It's a matter of design and philosophy that allows you to choose one or the other. Object oriented programming in C++ only works thru indirection, so it must use pointers and/or references, as objects cannot be used directly (in any language).

Think of the implementation being similar, except references are always dereferenced on use. This allows references to have direct access syntax (using .) and pointers use -> as in C.

You second example works because the reference is introducing indirection, that allows the object hierarchy's vtable to be used to select the correct function.
Last edited on
Another way of running the exact same code would be
No. The code would be:
1
2
3
4
5
6
7
8
9
10
11
12
13
void Stroke(Animal& animal)
{
	animal.MakeNoise(); // Note: . instead of ->
}

int main()
{
	Dog dog;
	Cat cat;
	Stroke(dog);
	Stroke(cat);
    return 0;
}

Use a pointer when you know that the object will be dynamically created [using new], otherwise use reference.
When you use a pointer you should check whether the pointer is nullptr.
A reference is used to refer to another object.

1
2
int a = 123;
int& r = a; // r refers to a 

The reference is used the same way as a regular variable. Any changes made to the reference will affect the original object.

1
2
r = -1;
std::cout << a; // prints -1 



A pointer points to another object. Pointers are a bit more verbose, so in order to get a pointer to an object you using the & operator. Note that this has nothing to do with the & symbol used for references. It's just the same symbol being reused for two different purposes.

1
2
int a = 123;
int* p = &a; // p points to a 

In order to access the object that is being pointed to you use the * operator.

1
2
*p = -2;
std::cout << a; // prints -2 



The above just shows the syntactical differences. A more fundamental difference is that references always refers to an object. After a reference has been intialized it is not possible to change which object the reference is referring to. With a pointer on the other hand you can change what object being pointed to as much as you want. You can even use a special null value to denote that the pointer doesn't point to any object.

1
2
3
4
5
6
7
8
9
10
11
int* p = nullptr;

// later in the code
if (p != nullptr)
{
	std::cout << "p points to an int that has value " << *p << ".\n";
}
else
{
	std::cout << "p does not point to anything.\n";
}



It is generally recommended to use references instead of pointers when possible because they are less verbose and not as error-prone, but sometimes you need the extra capabilities of pointers and then you will of course have to use them.

In your example there is no reason to use a pointer for the parameter to the Stroke function so I would strongly recommend using a reference in this case. Note that in your reference version of the Stroke function you should have used . instead of ->.

1
2
3
4
void Stroke(Animal& animal)
{
	animal.MakeNoise();
}


-> is only used on pointers. It's a convenient way of accessing a member of an object that's being pointed to by a pointer.
ptr->fun(); has the same meaning as (*ptr).fun();
Last edited on
Alright so I think I managed to get my head around the reference example I wrote this code just to fully understand the difference between using a reference and not using one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
	int a1 = 123;
	int r1 = a1;

	a1 = a1 + 5;

	int a2 = 123;
	int& r2 = a2;

	a2 = a2 + 5;

	std::cout << r1 << std::endl;
	std::cout << r2 << std::endl;
}


The inputs were as expexted r1 = 123 and r2 = 127

in order to get a pointer to an object you using the & operator. Note that this has nothing to do with the & symbol used for references. It's just the same symbol being reused for two different purposes.


So there are two meaning to the & symbol one is for referencing as stated in the example above, I don't quite understand the second purpose, what is it called ?

I'm sure what you wrote @Peter87 makes sense to many other people, but I can't seem to get a grasp on pointers yet, I don't understand whats their purpose, I can give you a text book answer that I had to memorize for tests but I don't understand what it means.

Note that in your reference version of the Stroke function you should have used . instead of ->.


So here both are acceptable but due to pointers being highly "unstable" we should always opt for the . when we have the choice to do so.

ptr->fun(); has the same meaning as (*ptr).fun();


This line right here, I feel that if I understand this I crack the enigma of pointers that is driving me absolutely crazy.

I'll attempt to explain from my own understanding now, pointers are used (*) when you want to point to another object meaning that *p has to point to a or b or c what have you, but cannot point to the number that directly represents a,b or c such as 123.

int* p = &a

I have no idea why in the hell we would put the second & meaning here this just makes everything a bit more confusing.

Returning to the other pointer ->, this is used to call a function similar to that of (.) and is used when ........... I don't know, damn. Someone please fill in the blanks.

Will you access different function if you put -> instead of (.) ?
@kbw I appreciate you writing down the explanation, but I need ground rules for when to apply one or the other, and how.

It's a matter of design and philosophy that allows you to choose one or the other


I'm sure this sentence makes sense to the more accustomed programmers, but without fully understanding them I don't think I can.
Not sure if this is going to be a silly request or not.

Could anyone attempt to give me a basic example comparing pointers * and -> to a feature in C# so I can see how it would work in another language.
1
2
3
4
5
int  a1 = 42;
int& r1 = a1; // r1 is a reference to a1
int* p1 = &a1; // take address of a1 and store it in p1
int  b1 = *p1; // fetch value from the address that p1 has
int  c1 = a1 & 14; // bitwise AND ==> c1 == 10 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct Point {
  int x;
  int y;
};

Point foo;
foo.x = 42; // access member x of Point foo
Point* bar = &foo;
(*bar).x = 7; // fetch value from the address that bar has
  // and then access member x of that Point
bar->y = 3; // fetch value from the address that bar has
  // and then access member y of that Point

bar[0].y = 9; // fetch value from the address bar+0
  // and then access member y of that Point

// int k = ...
// bar[k] == *(bar+k)
// bar[0] == *(bar+0) == *bar 
Last edited on
So there are two meaning to the & symbol one is for referencing as stated in the example above, I don't quite understand the second purpose, what is it called ?

To add to what keskiverto said:

1) When used in a definition or declaration, as part of a type, it means that the thing being declared with that type is a reference, e.g.

1
2
3
4
5
6
int a = 37;
int& r1 = a;  // r1 is a reference to a

void function1(int& r2); // function1 takes, as its argument, a reference.

int& function2();  // function2 returns a reference to an integer 


2) When it's used as a unary operator, it means "get the address of". It's called the address-of operator:

http://en.cppreference.com/w/cpp/language/operator_member_access#Built-in_address-of_operator

Since a pointer is an address, it gets used when you're dealing with pointers, e.g.

1
2
3
4
5
6
7
int a = 37;
int* p1;
p1 = &a;  // p1 now stores the address of a, i.e. it points to a

void function3(int* p2); // Declaration - function3 takes, as its argument, a pointer.
int b = 371;
function3(&b);  // Call function3, passing in the address of b, i.e. a pointer to b 


3) When used as a binary operator, it means "bitwise AND":

https://en.cppreference.com/w/cpp/language/operator_arithmetic#Bitwise_logic_operators


Last edited on
Peter87 wrote:
ptr->fun(); has the same meaning as (*ptr).fun();
GhettoBurger wrote:
This line right here, I feel that if I understand this I crack the enigma of pointers that is driving me absolutely crazy.

*ptr gives you the object that ptr points to.
(*ptr).fun() calls function fun() on that object.

The reason parentheses need to be used here is because *ptr.fun() would be interpreted as *(ptr.fun()), i.e. call fun() on ptr (which would need to be an object instead of a pointer) and get the object that is being pointed to by the return value (which means the function would need to return a pointer).
Yet more fun with parentheses:
1
2
3
4
int  * fun ( double ); // function
int (* fun)( double ); // pointer
int  * fun [ 42 ]; // array
int (* fun)[ 42 ]; // pointer 


C has pointers and syntax for them. C++ did inherit that.
C++ did add reference type and operator overloading. Some symbols are reused. Context matters.

C++ Standard Library offers more verbose types that let you use pointers indirectly.
Topic archived. No new replies allowed.