0% found this document useful (0 votes)
83 views28 pages

C++ Pointers References & Dynamic Memory Management

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
83 views28 pages

C++ Pointers References & Dynamic Memory Management

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

C++ Pointers &

References
C++ Dynamic Memory
Management
How computer Memory works and Quantum Computing as the future

YT Link (If Video Broken)


References
Creating References
A reference variable is a "reference" to an existing variable, and it is created with the & operator.

string food = "Pizza"; // food variable


string &meal = food; // reference to food

Now, we can use either the variable name food or the reference name meal to refer to the food variable.

Example:

string food = "Pizza";


string &meal = food;

cout << food << "\n"; // Outputs Pizza


cout << meal << "\n"; // Outputs Pizza
Memory Address

In the previous example, the & operator was used to


create a reference variable.
But it can also be used to get the memory address of a
variable;
which is the location of where the variable is stored on
the computer.

When a variable is created in C++, a memory address


is assigned to the variable.
And when we assign a value to the variable, it is stored
in this memory address.

To access it, use the & operator, and the result will
represent where the variable is stored.
Memory Address Example

string food = "Pizza";

cout << &food; // Outputs 0x6dfed4

**Note: The memory address is in hexadecimal form (0x..).


Note that you may not get the same result in your program.
References and Pointers (whic
h you will learn about in the
next section) are important in
And why is it C++, because they give you the
ability to manipulate the data in
useful to the computer's memory - which
can reduce the code and
know the improve the performance.
memory
address? These two features are one of
the things that make C++ stand
out from other programming
languages, like Python and Java.
Pointers
Pointers and Dynamic Memory Management Stack vs Heap Memory

YT Link (If Video Broken)


Creating Pointers

You previously learned that we can get


the memory address of a variable by using
the & operator.

Example:

string food = "Pizza"; // A food variable of


type string

cout << food; // Outputs the value of


food (Pizza)
cout << &food; // Outputs the memory
address of food (0x6dfed4)
Creating Pointers (Cont.)
• A pointer however, is a variable that stores the memory address as its value.
• A pointer variable points to a data type (like int or string) of the same type, and is created with
the * operator.
• The address of the variable you're working with is assigned to the pointer.

Example:

string food = "Pizza"; // A food variable of type string


string* ptr = &food; // A pointer variable, with the name ptr, that stores the address of
food

// Output the value of food (Pizza)


cout << food << "\n";

// Output the memory address of food (0x6dfed4)


cout << &food << "\n";

// Output the memory address of food with the pointer (0x6dfed4)


cout << ptr << "\n";
Create a pointer variable with the name ptr, that points
to a string variable, by using the asterisk sign * (string* ptr).

Note that the type of the pointer has to match the type of the variable
you're working with.
Creating
Use the & operator to store the memory address of the variable
called food, and assign it to the pointer.
Pointers
(Cont.)
Now, ptr holds the value of food's memory address.
Example
**Tip: There are three ways to declare pointer variables, but the first Explained
way is preferred:

string* mystring; // Preferred


string *mystring;
string * mystring;
Get Memory Address and Value

In the previous example, we used the


pointer variable to get the memory
Dereference address of a variable (used together
with the & reference operator).

However, you can also use the pointer


to get the value of the variable, by
using the * operator
(the dereference operator).
Dereference Example

string food = "Pizza"; // Variable declaration


string* ptr = &food; // Pointer declaration

// Reference: Output the memory address of food with the pointer (0x6dfed4)
cout << ptr << "\n";

// Dereference: Output the value of food with the pointer (Pizza)


cout << *ptr << "\n";

**Note that the * sign can be confusing here, as it does two different things in our code:

•When used in declaration (string* ptr), it creates a pointer variable.


•When not used in declaration, it act as a dereference operator.
Modify the Pointer Value
You can also change the string food = "Pizza";
pointer's value. string* ptr = &food;

But note that this will also // Output the value of food (Pizza)
cout << food << "\n";
change the value of the
original variable. // Output the memory address of food (0x6dfed4)
cout << &food << "\n";

Example: // Access the memory address of food and output its value (Pizza)
cout << *ptr << "\n";

// Change the value of the pointer


*ptr = "Hamburger";

// Output the new value of the pointer (Hamburger)


cout << *ptr << "\n";

// Output the new value of the food variable (Hamburger)


cout << food << "\n";
Reference Main Use Case:
Function Parameters/Arguments
References are primarily used in
The main use of references is
passing reference in/out of
acting as function formal
functions to allow the called
parameters to support pass-by-
function accesses variables in the
reference.
caller directly.

If a reference variable is passed


into a function, the function works Changes inside the function are
on the original copy (instead of a reflected outside the function.
clone copy in pass-by-value).
Function: Pass-by-Value vs. Pass-by-Reference
Pass-by-Value Pass-by-Reference

• In C++, by default, arguments are • In many situations, we may wish to


passed into functions by value (except modify the original copy directly
arrays which is treated as pointers). (especially in passing huge object or
• That is, a clone copy of the argument array) to avoid the overhead of
is made and passed into the function. cloning.
• Changes to the clone copy inside the • This can be done by passing a pointer
function has no effect to the original of the object into the function, known
argument in the caller. as pass-by-reference.
• In other words, the called function
has no access to the variables in the
caller.
Function: Pass-by-Value vs. Pass-by-Reference: Examples
Pass-by-Value Pass-by-Reference (with Pointer Arguments)
#include <iostream> /* Pass-by-reference using pointer */
#include <iostream>
using namespace std;
using namespace std;

int square(int);
void square(int *);
int main() {
int number = 8; int main() {

cout << "In main(): " << &number << endl; // 0x22ff1c int number = 8;
cout << "In main(): " << &number << endl; // 0x22ff1c
cout << number << endl; // 8
cout << number << endl; // 8
cout << square(number) << endl; // 64
square(&number); // Explicit referencing to pass an address
cout << number << endl; // 8 - no change
cout << number << endl; // 64
//The output clearly shows that there are two different addresses. //The called function operates on the same address, and can thus modify the variable
in the caller.
}
}
int square(int n) { // non-const
cout << "In square(): " << &n << endl; // 0x22ff00 void square(int * pNumber) { // Function takes an int pointer (non-const)
n *= n; // clone modified inside the function cout << "In square(): " << pNumber << endl; // 0x22ff1c

return n; *pNumber *= *pNumber; // Explicit de-referencing to get the value pointed-to

} }
Pass-by-Reference
/* Pass-by-reference using reference */
with Reference #include <iostream>
Arguments using namespace std;

Instead of passing pointers into function, you


could also pass references into function, to void square(int &);
avoid the clumsy syntax of referencing and
dereferencing.
int main() {
• Take note referencing (in the caller) and
dereferencing (in the function) are done int number = 8;
implicitly. cout << "In main(): " << &number << endl; // 0x22ff1c
• The only coding difference with pass-by- cout << number << endl; // 8
value is in the function's parameter square(number); // Implicit referencing (without '&')
declaration.
• Recall that references are to be cout << number << endl; // 64
initialized during declaration. //output shows that the called function operates on the same address, and can
• In the case of function formal parameter, thus modify the caller's variable.
the references are initialized when the }
function is invoked, to the caller's
arguments.
void square(int & rNumber) { // Function takes an int reference (non-const)
• References are primarily used in passing
reference in/out of functions to allow the cout << "In square(): " << &rNumber << endl; // 0x22ff1c
called function accesses variables in the rNumber *= rNumber; // Implicit de-referencing (without '*')
caller directly.
}
/* References vs. Pointers */
References vs. #include <iostream>

Pointers using namespace std;

int main() {
To get the value pointed to by a int number1 = 88, number2 = 22;
pointer, you need to use the
dereferencing operator *
(e.g., if pNumber is a int pointer, // Create a pointer pointing to number1
*pNumber returns the value
int * pNumber1 = &number1; // Explicit referencing
pointed to by pNumber. It is called
dereferencing or indirection). *pNumber1 = 99; // Explicit dereferencing
• To assign an address of a variable cout << *pNumber1 << endl; // 99
into a pointer, you need to use
the address-of operator & cout << &number1 << endl; // 0x22ff18
(e.g., pNumber = &number). cout << pNumber1 << endl; // 0x22ff18 (content of the
pointer variable - same as above)
cout << &pNumber1 << endl; // 0x22ff10 (address of the
pointer variable)
pNumber1 = &number2; // Pointer can be reassigned to
store another address
}
/* References vs. Pointers */

References vs. #include <iostream>


using namespace std;
Pointers
int main() {
int number1 = 88, number2 = 22;
On the other hand, referencing
and dereferencing are done on // Create a reference (alias) to number1
the references implicitly.
int & refNumber1 = number1; // Implicit referencing (NOT &number1)
• For example, if refNumber is a refNumber1 = 11; // Implicit dereferencing (NOT *refNumber1)
reference (alias) to another int
cout << refNumber1 << endl; // 11
variable, refNumber returns the
value of the variable. cout << &number1 << endl; // 0x22ff18
cout << &refNumber1 << endl; // 0x22ff18
• No explicit dereferencing
operator * should be used. //refNumber1 = &number2; // Error! Reference cannot be re-assigned
// error: invalid conversion from 'int*' to 'int'
• Furthermore, to assign an
address of a variable to a refNumber1 = number2; // refNumber1 is still an alias to number1.

reference variable, no address- // Assign value of number2 (22) to refNumber1 (and number1).
of operator & is needed. number2++;
cout << refNumber1 << endl; // 22
cout << number1 << endl; // 22
cout << number2 << endl; // 23
}
Static vs. Dynamic Memory Allocation

Static Allocation Dynamic Allocation


• You, as the programmer, handle the
memory allocation and deallocation
• In static allocation, the compiler yourself (via new and delete
allocates and deallocates the operators).
storage automatically, and • You have full control on the pointer
handles memory management. addresses and their contents, as
• Static allocated entities are well as memory management.
manipulated through named • Dynamic allocated entities are
variables. handled through pointers.
Dynamic Memory
// Static allocation
Allocation int number = 88;
new and delete Operators
int * p1 = &number; // Assign a "valid" address into pointer
Instead of defining an int variable (int
number), and assign the address of the // Dynamic Allocation
variable to the int pointer (int int * p2; // Not initialize, points to somewhere which is
*pNumber = &number), the storage invalid
can be dynamically allocated at cout << p2 << endl; // Print address before allocation
runtime, via a new operator.
p2 = new int; // Dynamically allocate an int and assign its
In C++, whenever you allocate a piece address to pointer
of memory dynamically via new, you
need to use delete to remove the // The pointer gets a valid address with memory
storage (i.e., to return the storage to allocated
the heap). *p2 = 99;
• The new operator returns a pointer cout << p2 << endl; // Print address after allocation
to the memory allocated. cout << *p2 << endl; // Print value point-to
• The delete operator takes a pointer delete p2; // Remove the dynamically allocated storage
(pointing to the memory allocated
via new) as its sole argument.
initialize the allocated memory
// use an initializer to initialize a fundamental type (such as int, double)
int * p1 = new int(88);
double * p2 = new double(1.23);

// C++11 brace initialization syntax


int * p1 = new int {88};
double * p2 = new double {1.23};

cout << *p1 << "\n" << *p2 << endl;


// Dynamically allocate global pointers
#include <iostream>
Dynamically allocate using namespace std;

storage for global int * p1, * p2; // Global int pointers


pointers inside a function
// This function allocates storage for the int*
// which is available outside the function
Dynamically allocated storage inside the void allocate() {
function remains even after the function p1 = new int; // Allocate memory, initial content unknown
exits.
*p1 = 88; // Assign value into location pointed to by pointer
p2 = new int(99); // Allocate and initialize
}

int main() {
allocate();
cout << *p1 << endl; // 88
cout << *p2 << endl; // 99
delete p1; // Deallocate
delete p2;
return 0;
}
Array is Treated as
/* Pointer and Array (TestPointerArray.cpp) */
Pointer #include <iostream>
using namespace std;

In C++, an array's name is a pointer, pointing int main() {


to the first element (index 0) of the array.
const int SIZE = 5;
For example, suppose that numbers is an int
int numbers[SIZE] = {11, 22, 44, 21, 41}; // An int array
array,
• numbers is a also an int pointer, pointing
// The array name numbers is an int pointer, pointing at the
at the first element of the array.
// first item of the array, i.e., numbers = &numbers[0]
• That is, numbers is the same as
&numbers[0]. cout << &numbers[0] << endl; // Print address of first element
(0x22fef8)
• Consequently, *numbers is number[0]; cout << numbers << endl; // Same as above (0x22fef8)
• *(numbers+i) is numbers[i]. cout << *numbers << endl; // Same as numbers[0] (11)
cout << *(numbers + 1) << endl; // Same as numbers[1] (22)
cout << *(numbers + 4) << endl; // Same as numbers[4] (41)
}
/* Test dynamic allocation of array */
#include <iostream>
Dynamic Memory using namespace std;
Allocation
new[] and delete[] Operators int main() {
const int SIZE = 5;
int * pArray;
Dynamic array is allocated at runtime
rather than compile-time, via the new[]
operator. pArray = new int[SIZE]; // Allocate array via new[] operator

To remove the storage, you need to use


// Assign random numbers between 0 and 99
the delete[] operator (instead of simply
delete). for (int i = 0; i < SIZE; ++i) {
*(pArray + i) = rand() % 100;
}
// Print array
for (int i = 0; i < SIZE; ++i) {
cout << *(pArray + i) << " ";
}
cout << endl;

delete[] pArray; // Deallocate array via delete[] operator


return 0;
}
Summary

However, you need to understand the syntaxes of pass-by-reference


Pointers and For novices, avoid with pointers and references, because they are used in many library
references are using pointers in functions.
highly complex your program.
and difficult to In pass-by-value, a clone is made and passed into the function.
master.
But they can greatly Improper usage can lead
improve the efficiency of to serious logical bugs.
• The caller's copy cannot be modified.
the programs. In pass-by-reference, a pointer is passed into the function.
• The caller's copy could be modified inside the function.
In pass-by-reference with reference arguments, you use the variable name as the
argument.
In pass-by-reference with pointer arguments, you need to use &varName (an address)
as the argument.

You might also like