Powered by
/src$ make
  • Home
  • About
  • Directory
  • Contact
  • Home
  • About
  • Directory
  • Contact

C++ Pointer and Reference Tutorial

9/8/2018

 

Introduction - Memory Management is kind of a Big Deal

Controlled memory management is one of the most important features that C++ (and C) have that other other famous programming languages (like Java, C#, Python) don't have. Although the other languages often give you what you need to work with data, C++ allows for very fine-tuned control of data because of the use of pointers.

We'll define what pointers and references are, and go over all of the possible code examples you'd use them in. (It's especially important to know for function parameters, since it saves a LOT of time if you pass by pointer or reference.)
Note: This topic is a bit difficult for beginner programmers, and if you learn Java first, you'll never really even learn about pointers since the language doesn't use them (although Java does use references) Still, learning about it is worthwhile.

What Are Pointers and References?

To start out with, remember that in programming, our data (variables, objects, everything) lives in memory (RAM, specifically), and so each variable in our program has a specific address corresponding to it's specific location in memory. 
A pointer is a C++ variable that stores the address of some other variable.  
1
2
3
4
5
6
7
8
9
// Declare an integer variable named srcmake and set it to be 5.
int srcmake = 5; 
    
// Create a pointer to an integer variable named srcmakePointer
// and set it equal to the address of the variable named srcmake.
int* srcmakePointer = &srcmake;
    
// Print whatever is inside the address that srcmakePointer points to.
cout << *srcmakePointer; // 5
Picture
Pointers store the RAM address of a variable.
Note that pointer syntax is to declare a variable with an asterisk * next to it, accessing the address of a variable with with an ampersand &, and dereferencing a pointer (accessing whatever is inside the address of a pointer) is also with an asterisk *.
Think of a pointer like knowing a specific index in an array: if you know the direct index, you can just look directly to find the variable you want.
A reference is when two variables refer to the same data in memory. You'll know because references use the & sign.
1
2
3
4
5
6
7
8
// Initialize a variable named a.
int a = 5;

// b is an integer that refers to the same value (in memory) as a.
int& b = a;

// If you change b, you also change a.
b = 2; // Now a=2 as well, because the integer in memory changed.
Picture
In C++, references are very helpful in function calls, either to update an external variable value inside the function, or to make sure you don't need to copy a large data structure like a vector unnecessarily.
(Note: We're using lvalue references specifically. rvalue references are an advanced topic that we'll talk about in another tutorial. (If that doesn't make sense, don't worry.))

Pass By Copy To Function

Passing a copy of a variable does not change the original variable. When the function PassByCopy is called, a new variable named srcmake2 is created in memory, and the value of srcmake2 is set to whatever was in srcmake1's value was at the time.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
using namespace std;

void PassByCopy(int srcmake2)
    {
    // Change the value that gets passed in and print it.
    srcmake2 = 10;
    cout << srcmake2 << endl;
    }

int main()
    {
    int srcmake1 = 5; 
    
    PassByCopy(srcmake1);
    
    // Print the value of srcmake1.
    cout << srcmake1 << endl;
    
    return 0;
    }
Output: 10 5
Picture
Passing a copy of a variable just creates a new variable in memory with the same value as the original.

​Pass By Reference To Function

Passing a variable by reference means that the function's variable (srcmake2) is actually the same data in memory as the original. That means any changes to the referenced variable will affect the original (and any other function calls using that reference). 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
using namespace std;

void PassByReference(int &srcmake2) // <- THE ONLY DIFFERENCE
    {
    // Change the value that gets passed in and print it.
    srcmake2 = 10;
    cout << srcmake2 << endl;
    }

int main()
    {
    int srcmake1 = 5; 
    
    PassByReference(srcmake1);
    
    // Print the value of srcmake1.
    cout << srcmake1 << endl;
    
    return 0;
    }
Output: 10 10
Note the only real difference is the & sign next to the function parameter, srcmake2, where we declare that we're passing the variable by reference.
Picture
Passing by reference doesn't create a new variable in memory, it just uses the same variable as the original.

Pass By Pointer To Function

Passing a pointer to a function is really dumb, and you should only really do it if you're working with linked lists or trees. 

Notice the three changes:
​1) When we call the function, we need to pass the address of the variable, instead of the variable itself.
2) In the functions parameters, we have to use a * to indicate the variable is a pointer.
3) Whenever we actually want to use the variable in the function, we have to reference it.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
using namespace std;

void PassByPointer(int *srcmake2) // <- PASSING A POINTER
    {
    // Change the value that gets passed in and print it.
    *srcmake2 = 10;                 // DEREFERENCE TO ACCESS VARIABLE
    cout << *srcmake2 << endl;    // DEREFERENCE TO ACCESS VARIABLE
    }

int main()
    {
    int srcmake1 = 5; 
    
    PassByPointer(&srcmake1);    // PASS THE ADDRESS OF srcmake1
    
    // Print the value of srcmake1.
    cout << srcmake1 << endl;
    
    return 0;
    }
Output: 10 10
Pass by reference if you can. Passing by pointers (for the sake of updating the variables outside of function scope) is annoying.

Pass A Pointer By Reference

Sometimes you need to update a pointer using a function, and so you can pass a pointer by reference. It works the same way as passing a variable by reference: updating the pointer inside of the function will update the pointer in memory (so it's a global change). 
 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
#include<iostream>
using namespace std;

// Passing a pointer to an integer, by reference.
void PassPointerByReference(int *&srcmakePointer) 
    {
    int srcmake2 = 10;
    // Make srcmakePointer point to the address of the variable srcmake2.
    srcmakePointer = &srcmake2;
    cout << *srcmakePointer << endl;    // Dereference to get the value.
    }

int main()
    {
    int srcmake1 = 5; 
    int *srcmakePointer = &srcmake1;
    
    // Dereferencing the pointer to get the value.
    cout << *srcmakePointer << endl;
    
    PassPointerByReference(srcmakePointer);    
    
    // Dereferencing the pointer to get the value.
    cout << *srcmakePointer << endl;
    
    return 0;
    }
Output: 5 10 10

Pass A Pointer By Pointer

A really convoluted way to change the value of a pointer after using a function is to pass a pointer to the pointer, and then dereferencing the pointer to the pointer to change the actual pointer value. Sound confusing? That's because it's dumb. Pass a pointer by reference, like in the last section, if you need too. Still, if you see someone use a ** in the function parameter and don't know what it means, then check this code out.
 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
#include<iostream>
using namespace std;

// Passing a pointer to an integer, by reference.
void PassPointerByPointer(int **srcmakePointer2) 
    {
    // Create a new variable and a pointer to that variable.
    int srcmake2 = 10;
    * srcmakePointer2 = &srcmake2;
    
    // Make srmakePointer1 now point to srcmake2
    // By dereferencing srcmakePointer2 and setting it equal to the address of srcmake2...
    *srcmakePointer2 = & srcmake2;
    }

int main()
    {
    int srcmake = 5; 
    int *srcmakePointer1 = &srcmake;
    
    // Dereferencing the pointer to get the value.
    cout << *srcmakePointer1 << endl;
    
    // Pass the address of the pointer.
    PassPointerByPointer(&srcmakePointer1);
    
    // Dereferencing the pointer to get the value.
    cout << *srcmakePointer1 << endl;
    
    return 0;
    }
Output: 5 10
Picture
The original variable "srcmake" exists, and srcmakePointer1 stores the address of that variable. "srcmakePointer2" stores the address of the pointer "srcmakePointer1".

Bonus: Pass A String As Const Char*

Sometimes you'll see people pass a string as "const char*". It's a little weird, but it's just a pointer to a string. Here's some code explaining how it works.
 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
#include <iostream>
#include <string.h>
using namespace std;

void PassConstChar(const char* mystring)
    {
    // Get the size.
    int size = strlen(mystring);
    cout << "Size is: " << size << endl;
    cout << "Word is: " << mystring << endl;
    
    // Convert the char* to an actual string.
    string convertedstring = string(mystring);
    cout << "String version: " << convertedstring << endl;
    
    // Traverse the chars char by char.
    for(int i = 0; i < size; i++)
        {
        char c = mystring[i];
        cout << c << " ";
        }
    cout << endl;
    }

int main() 
    {
    // A pointer to a character.
    const char* mystring = "srcmake";
    PassConstChar(mystring);
    return 0;
    }
Output: Size is: 7
Word is: srcmake
String version: srcmake
​s r c m a k e

Conclusion

This is a lot of information to take in, but understanding the fundamentals of memory, pointers, and references will help you write more efficient code (and understand what other people's code).  It might seem like this code isn't necessary, but even using fundamental data structures likes trees and linked lists require using pointers, so you need to know them.
​Like this content and want more? Feel free to look around and find another blog post that interests you. You can also contact me through one of the various social media channels. 

Twitter: @srcmake
Discord: srcmake#3644
Youtube: srcmake
Twitch: www.twitch.tv/srcmake
​Github: srcmake

Comments are closed.

    Author

    Hi, I'm srcmake. I play video games and develop software. 

    Pro-tip: Click the "DIRECTORY" button in the menu to find a list of blog posts.
    Metamask tip button
    License: All code and instructions are provided under the MIT License.

    Discord

    Chat with me.


    Youtube

    Watch my videos.


    Twitter

    Get the latest news.


    Twitch

    See the me code live.


    Github

    My latest projects.

Powered by Create your own unique website with customizable templates.