Pointers
Concept
• Every variable is assigned a memory
location whose address can be retrieved
using the address operator &
• The address of a memory location is
called a pointer
Memory Every variable in an executing
program is allocated a section of
int main()
{
allocation for memory large enough to hold a int numStudents;
variables value of that variable’s type.
double fees;
….
Current C++ compilers that run
…..
on PCs usually allocate:
return 0;
1 byte 🡪 char
2 bytes 🡪 short }
4 bytes 🡪 float and long
8 bytes 🡪 double
• Each byte of memory has a unique address
Memory allocation • A variable’s address is the address of the 1st byte
allocated to it
• Suppose that the following variables are defined:
char letter; short number; float amount;
Address operator 🡪 &
• Address operator & can be used to retrieve the address of any variable.
• Place it before the variable whose address you want
&amount 🡨 returns the memory address
cout ≪ long(&amount); 🡨 displays the address to the screen
• By default, C++ prints addresses in hexadecimal. Cast it to long to make the
address print in the usual decimal format
char letter; Address of letter is: 4468752
short number; Address of number is: 4468754
float amount; Address of amount is: 4468756
double profit; Address of profit is: 4468760
char ch; Address of ch is: 4468768
int main()
{
cout << "Address of letter is: " << long(&letter) << endl;
cout << "Address of number is: " << long(&number) << endl;
cout << "Address of amount is: " << long(&amount) << endl;
cout << "Address of profit is: " << long(&profit) << endl;
cout << "Address of ch is: " << long(&ch) << endl;
return 0;
}
Concept
• A pointer variable is a variable
that holds addresses of memory
locations.
Pointers
• Memory addresses can be stored in variables of the appropriate type.
• A variable that stores an address is called a pointer variable, or simply,
pointer
• The definition of a pointer variable must specify the type of data that ptr will
point to
int *ptr;
Pointers
int *ptr;
• The asterisk before the variable name indicates that ptr is a pointer variable
• Int data type indicates that ptr can only be used to point to, or hold addresses of
integer variables.
• This definition is read as “ptr is a pointer to int”
• * is called the “indirection operator”
Various syntax styles
int * ptr int* ptr
int *ptr
int main()
Store and print an address
{
int x = 25; // int variable
int *ptr; // Pointer var, can point to an int
ptr = &x; // Store the address of x in ptr
cout << "The value in x is " << x << endl;
cout << "The address of x is " << ptr << endl;
return 0;
}
The value in x is 25 The address of x is 0x7e00
int main() The value in x is 25 The address of x is 0x7e00
{
int x = 25; // int variable
int *ptr; // Pointer var, can point to an int
ptr = &x; // Store the address of x in ptr
cout << "The value in x is " << x << endl;
cout << "The address of x is " << ptr << endl;
return 0;
}
Indirectly access and
modify variables
•When the indirection operator, * is
placed in front of a pointer variable
name, it dereferences the pointer.
•When you are working with a
dereferenced pointer, you are actually
working with the value the pointer is
pointing to.
int main()
{
int x = 25;
int *ptr;
ptr = &x;
cout << "Here is the value in x, printed twice:\n";
cout << x << " " << *ptr << endl;
*ptr = 100; “Dereferences” the pointer
Changes “x”
cout << "Once again, here is the value in x:\n";
cout << x << " " << *ptr << endl;
return 0;
}
Here is the value in x, printed twice:
25 25
Once again, here is the value in x:
100 100
int main()
{
int x = 25, y = 50, z = 75; // Three int variables Po i
int *ptr; // Pointer variable nter
diff s
eren can p
cout << "Here are the values of x, y, and z:\n";
t va o int
cout << x << " " << y << " " << z << endl; riab to
les
// Use the pointer to manipulate x, y, and z
ptr = &x; // Store the address of x in ptr
*ptr *= 2; // Multiply value in x by 2
ptr = &y; // Store the address of y in ptr
*ptr *= 2; // Multiply value in y by 2
ptr = &z; // Store the address of z in ptr
*ptr *= 2; // Multiply value in z by 2
// Display the contents of x, y, and z Here are the values of x, y, and z:
cout << "Once again, here are the values "
<< "of x, y, and z:\n"; 25 50 75
cout << x << " " << y << " " << z << endl; Once again, here are the values of x, y, and z:
return 0; 50 100 150
}
3 different uses for the asterisk (*)
As the multiplication operator:
• distance = speed * time;
In the definition of a pointer variable, such as
• int *ptr;
As the indirection operator, in statements such as
• *ptr = 100;
The Relationship Between Arrays and Pointers
Concept
Array names can be used as pointer
constants, and pointers can be used as
array names.
Array review
int grades[ ] = [90,100,85];
• To display the 3 grades in the grades array:
for (int x = 0; x < 3; x++)
cout << grades[x] << endl;
• You were told to NOT ever use grades without the subscript:
cout << grades;
int grades[ ] = [90,100,85]; 90 100 85
• What happens if we use an array variable without a subscript?
It contains the memory address of the first block of memory allocated to the
array
Remember arrays were always sent to functions as “pass by reference”?
calcFunction(grades);
void calcFunction(int grades[ ])…
Concept
int grades[] = [90,100,85];
Array name (grades), without brackets and a
subscript, actually represents the starting address
of the array.
This means that an array name is really a pointer.
int main()
{
short numbers[] = {10, 20, 30, 40, 50};
cout << "The first element of the array is ";
cout << *numbers << endl;
return 0;
} The first element of the array is 10
Because numbers works like a pointer to the starting address of the array,
the first element is retrieved when numbers is dereferenced.
How could the entire contents of an array be retrieved
using the indirection operator?
• Remember that array elements are stored together in memory
how could the entire contents of an array be retrieved
using the indirection operator?
If numbers is the address of numbers[0], values could be added to numbers
to get the addresses of the other elements in the array.
It’s important to know, however, that pointers do not work like regular
variables when used in mathematical statements.
how could the entire contents of an array be retrieved
using the indirection operator?
In C++, when you add a value to a pointer, you are actually adding that value
times the size of the data type being referenced by the pointer.
In other words, if you add one to numbers, you are actually adding 1 *
sizeof(short) to numbers.
If you add two to numbers, the result is numbers + 2 * sizeof(short), and so
forth.
• On a PC, this means the following are true because short integers
typically use 2 bytes:
• *(numbers + 1) is the value at address numbers + 1 * 2 *(numbers + 2)
is the value at address numbers + 2 * 2 *(numbers + 3) is the value at
address numbers + 3 * 2
• This automatic conversion means that an element in an array can be
retrieved by using its subscript or by adding its subscript to a pointer
to the array.
• If the expression *numbers, which is the same as *(numbers + 0),
retrieves the first element in the array, then *(numbers + 1) retrieves
the second element. Likewise, *(numbers + 2) retrieves the third
element, and so forth.
Note
• The parentheses are critical when adding values to pointers
• The * operator has precedence over the + operator, so the expression
*numbers + 1 is not equivalent to *(numbers + 1)
• The expression *numbers + 1 adds one to the contents of the first
element of the array, while *(numbers + 1) adds one to the address in
numbers, then dereferences it
int main()
{
array
const int SIZE = 5; [inde
x] i s
int numbers[SIZE]; equiv
a l e nt
to *(a
rra y +
cout << "Enter " << SIZE << " numbers: "; index
)
for (int count = 0; count < SIZE; count++)
cin >> *(numbers + count);
cout << "Here are the numbers you entered:\n";
for (int count = 0; count < SIZE; count++)
cout << *(numbers + count) << " ";
return 0;
}
Enter 5 numbers: 5 10 15 20 25 [Enter]
Here are the numbers you entered:
5 10 15 20 25
• The code on the next slide demonstrates how close the relationship is
between array names and pointers
• It defines an array of doubles and a double pointer, which is assigned
the starting address of the array.
• Not only is pointer notation then used with the array name, but
subscript notation is used with the pointer!
const int NUM_COINS = 5;
double coins[NUM_COINS] = {0.05, 0.1, 0.25, 0.5, 1.0};
double *doublePtr; // Pointer to a double
// Assign the address of the coins array to doublePtr
doublePtr = coins;
Notice that th
e address ope
assigned to a rator is not ne
// Display the contents of the coins array pointer. Since eded when an
use of the & the name of a array’s addre
// Use subscripts with the pointer! operator wou n array is alre ss is
ld be incorrec ady an addres
t s,
cout << "Here are the values in the coins array:\n";
for (int count = 0; count < NUM_COINS; count++)
cout << doublePtr[count] << " ";
// Display the contents of the coins array again, but
// this time use pointer notation with the array name!
Here are the values in the coins array:
cout << "\nAnd here they are again:\n"; 0.05 0.1 0.25 0.5 1
for (int count = 0; count < NUM_COINS; count++) And here they are again:
cout << *(coins + count) << " "; 0.05 0.1 0.25 0.5 1
There is ONE difference between array names and pointer variables
• You can NOT change the address an array name points to
• Array names are pointer constants
double readings[20], totals[20];
double *dptr;
dptr = readings; 🡨 Legal
dptr = totals; 🡨 Legal
readings = totals; 🡨 ILLEGAL Cannot change readings
totals = dptr; 🡨 ILLEGAL Cannot change totals
Concept
Pointers can be modified by adding
or subtracting integer values
const int SIZE = 8;
int numbers[ ] = {5, 10, 15, 20, 25, 30, 35, 40};
int *numPtr; // Pointer
Increment o
numPtr = numbers; perator adds
the size of o
to numPtr, s ne integer
o it points to
the array. the next ele
cout << "The numbers in the array are:\n"; ment in
Likewise, th
e de c r e m e n
for (int index = 0; index < SIZE; index++) size of one
integer from
t operator su
bt r a c t s t he
{ the pointer.
cout << *numPtr << " ";
numPtr++;
}
cout << "\nThe numbers in reverse order are:\n";
for (int index = 0; index < SIZE; index++)
The numbers in the array are:
{
numPtr--; 5 10 15 20 25 30 35 40
cout << *numPtr << " "; The numbers in reverse order are:
} 40 35 30 25 20 15 10 5
Arithmetic operations allowed on pointers
• ++
• --
• +=
• -=
• Pointer can be subtracted from another pointer
• Not allowed 🡪 multiplication or division
Concept
Pointers may only be
initialized with the address
of an existing object
Correct pointer initializations
int myValue;
int *pint = &myValue; 🡨 LEGAL
int ages[20];
int *pint = ages; 🡨 LEGAL
Incorrect pointer initializations
float myFloat;
int *pint = &myFloat; 🡨 ILLEGAL
int *pint = &myValue;
int myValue; 🡨 ILLEGAL
Defining pointers in the same statement
int myValue, *pint = &myValue; 🡪 LEGAL
double readings[50], *marker = readings; 🡪 LEGAL
Handling pointers that do NOT currently
point to a valid memory location
• Older versions of C++ 🡪 assign the address 0 to a pointer
int *ptrToint = 0;
double *ptrToDouble = 0;
Handling pointers that do NOT currently point to a valid memory location
• Many header files (iostream, fstream, cstdlib) define a constant named
NULL to represent the pointer value 0
int *ptrToint = NULL;
double *ptrToDouble = NULL;
NOTE: Many people prefer this form because NULL is clearly
recognized as denoting the address 0 rather than the integer 0.
Regardless, a pointer whose value is 0 is called a null pointer.
Handling pointers that do NOT currently
point to a valid memory location
• C++ 11 defines the key word nullptr to indicate an invalid
memory address
int *ptrToint = nullptr;
double *ptrToDouble = nullptr;
Testing pointers for 0, NULL, or nullptr
if (p != nullptr) { // use the pointer p . . . }
if (p != NULL) { // use the pointer p . . . }
if (p != 0) { // use the pointer p . . . }
The pointer will only be used if it does NOT evaluate to 0, so each of
the above tests is equivalent to
if (p) { // use the pointer p . . . }
In C++ 11, putting an empty pair
of braces { } at the end of a
variable definition initializes the
variable to its defaultvalue.
Concept
Default values
• Default value for numeric types such as int, long, and double is zero
• Default value for pointer types is nullptr.
int myInt = 0; int myInt{ };
double myDouble = 0.0; 🡪 double myDouble{ };
int *ptrToInt = nullptr; int *ptrToInt{ };
EQUIVALENT
It is important to be able to check whether a
pointer has been assigned a correct value.
Pointer For this reason, pointers should always be
initialized or assigned a value close to where
they are defined.
notes Also, a pointer that is no longer pointing to a
valid location should be assigned a value of
nullptr unless the pointer is going out of scope
or the program is about to terminate.
Comparing Pointers
C++’s relational operators may be used to
compare pointer values
Can use these operators with pointers
> < == != >= <=
&array[1] > &array[0]
array < &array[4] 🡨 All are “true”
array == &array[0]
&array[2] != &array[3]
Comparing 2 pointers is NOT the same as
comparing the values 2 pointers point to
if (ptr1 < ptr2) 🡨 compares the addresses
If (*ptr1 < *ptr2) 🡨 compares the values that
ptr1 and ptr2 point to
Array bounds checking
The capability of comparing addresses gives
you another way to be sure a pointer does
NOT go beyond the boundaries of an array
const int SIZE = 8;
int numbers[ ] = {5, 10, 15, 20, 25, 30, 35, 40};
int *numPtr = numbers;
cout << "The numbers in the array are:\n";
cout << *numPtr << " "; // Display first element
while (numPtr < &numbers[SIZE-1])
{
numPtr++;
cout << *numPtr << " ";
}
cout << "\nThe numbers in reverse order are:\n";
cout << *numPtr << " "; // Display last element
while (numPtr > numbers) The numbers in the array are:
{
5 10 15 20 25 30 35 40
numPtr--;
cout << *numPtr << " "; The numbers in reverse order are:
} 40 35 30 25 20 15 10 5
Common use of comparisons
• Most comparisons involving pointers compare a pointer to 0, NULL,
or nullptr to determine whether the pointer points to a legitimate
address
if (ptrToInt != nullptr)
cout ≪ *ptrToInt;
else
cout ≪ "null pointer";
Concepts
A pointer can be used as a
function parameter
Pointer function parameters
• By using a pointer parameter, it give the
function access to the original argument
• Like a reference parameter does
Remember reference parameters?
• A reference variable acts as an alias to the original variable used as an
argument.
• This gives the function access to the original argument variable,
allowing it to change the variable’s contents.
• When a variable is passed into a reference parameter, the argument is
said to be passed by reference.
Pass by Reference vs Pass by Pointer example
int balance; int balance;
balance = 100; balance = 100;
doubleTheValue(balance); doubleTheValue(&balance);
void doubleTheValue(int &balance){ void doubleTheValue(int *balance){
balance *= 2; *balance *= 2;
} }
Pass by Pointer notes
• Reference variables are easier to work with than pointers
• Reference variables hides all the “mechanics” of dereferencing and
indirection
• Reason to learn this technic?
• In C, the only way to get the effect of pass by reference was to use a pointer
Concept
A pointer to a A constant pointer
constant may NOT may NOT be
be used to change changed after it has
the value it points to been initialized
Pointers to Constants
• Use of constants secures your data from accidental changes
• If you need to pass a const item into a pointer, then the pointer must
also be defined as a pointer to a const item
Example
const int SIZE = 6;
const double payRates[SIZE] = { 18.55, 17.45, 12.85, 14.97, 10.35, 18.89 };
displayPayRates(payRates);
void displayPayRates(const double *rates, int size) {
cout ≪ setprecision(2) ≪ fixed ≪ showpoint;
for (int count = 0; count < size; count++) {
cout ≪ "Pay rate for employee " ≪ (count + 1) ≪ " is $" ≪
*(rates + count) ≪ endl;
}
}
Compiler will NOT allow us to write code that changes the thing that rates points to
Passing a Non-Constant argument into a
“Pointer to a Constant”
• A pointer to a const can receive the address of a non-constant item
const int SIZE = 6;
const int array1[SIZE] = { 1, 2, 3, 4, 5, 6 };
int array2[SIZE] = { 2, 4, 6, 8, 10, 12 };
displayValues(array1, SIZE);
displayValues(array2, SIZE);
void displayValues(const int *numbers, int size)
{
// Display all the values
for (int count = 0; count < size; count++)
{
cout << *(numbers + count) << " ";
}
cout << endl;
}
Non constant data to constant pointer
params
When writing a function that uses a pointer parameter, and the function
is not intended to change the data the parameter points to, it is always a
good idea to make the parameter a pointer to const.
Not only will this protect you from writing code in the function that
accidentally changes the argument, but the function will be able to
accept the addresses of both constant and non-constant arguments.
Constant Pointers
• A pointer to const points to a constant item
• Data that the pointer points to can NOT change, but the pointer itself can change
• With a const pointer, it is the pointer itself that is constant
• Once the pointer is initialized with an address, it cannot point to anything else
int value = 22;
int * const ptr = &value;
ptr = 0; 🡨 ERROR!
*ptr = 0; 🡨 LEGAL: changing the data not the pointer
Constant Pointers to Constants
int value = 22;
const int * const ptr = &value;
Can NOT change the value of ptr
Can NOT change the data that ptr points to
Concept
Variables may be created and
destroyed while a program is
running
Number of variables is known…
• As long as you know how many variables you will need during the
execution of a program, you can define those variables up front.
• For example, a program to calculate the area of a rectangle will need
three variables: one for the rectangle’s length, one for the rectangle’s
width, and one to hold the area.
• If you are writing a program to compute the payroll for 30 employees,
you’ll probably create an array of 30 elements to hold the amount of
pay for each person.
Number of variables is unknown…
• Suppose you want to write a test-averaging program that will average ANY
number of tests.
• Obviously, the program would be very versatile, but how do you store the
individual test scores in memory if you don’t know how many variables to
define?
• Use an array? How big? Guess? Probably have about 50 tests so create
an array of 100 to be safe?
• Now we have allocated (wasted) twice as much space as the program will probably
use
Dynamic
memory
allocation
With pointers, you can allow the
program to create its own variables
“on the fly”
Dynamic memory allocation
• To dynamically allocate memory means that a program, while running,
asks the computer to set aside a chunk of unused memory large
enough to hold a variable of a specific data type
• Let’s say a program needs to create an integer variable
• It will make a request to the computer that it allocate enough bytes to store an
int.
Dynamic memory allocation
• When the computer fills this request, it finds and sets aside a chunk of
unused memory large enough for the variable.
• It then gives the program the starting address of the chunk of memory.
• The program can only access the newly allocated memory through its
address, so a pointer is required to use those bytes.
The new operator
int *iptr = nullptr;
Use the new operator to dynamically allocate an
integer variable and assign the address of the newly
allocated variable to iptr
iptr = new int;
int *iptr = nullptr; The new operator
iptr = new int;
The new operator
A value may be stored in this new variable by
dereferencing the pointer:
*iptr = 25;
The new operator
Any other operation may be performed on the new
variable by simply using the dereferenced pointer
cout ≪ *iptr; // Display the contents of the new variable
cin ≫ *iptr; // Let the user input a value
total += *iptr; // Use the new variable in a computation.
Dynamically allocating an array
There’s little purpose in dynamically allocating a
single variable.
A more practical use of the new operator is to
dynamically create an array
Dynamically allocating an array
int *iptr = nullptr;
iptr = new int[100];
Loop using subscript notation to store a one in each
element of the array:
for (int count = 0; count < 100; count++) iptr[count]
= 1;
• Every call to new allocates storage from a special area of the
program’s memory called the heap.
• If a program makes a lot of requests for dynamic memory, the heap
will eventually become depleted, and additional calls to new will fail.
• When this happens, the C++ runtime system will throw a bad_alloc
exception to notify the calling program that the requested memory
cannot be allocated.
Exceptions
• An exception is a mechanism for notifying a program that something
has gone drastically wrong with the operation that was being executed
and that the results of the operation cannot be trusted.
• The default action of an exception is to force the executing program to
terminate.
• A program that has finished using a dynamically allocated block of memory
should free the memory and return it to the heap to make it available for
future use.
• This is accomplished by calling the delete operator and passing it the
address of the memory to be deallocated.
• After delete has completed, the value of the pointer should be set to nullptr
to indicate that it is no longer valid.
• The only exception to this rule is in situations (such as at the end of the program)
where it is clear that the deleted pointer will never be used again.
Delete operator with single variables
delete iptr;
iptr = nullptr;
Delete operator with arrays (use [ ] )
delete [ ] iptr;
iptr = nullptr;
Delete operator notes
• Unless a pointer is going out of scope, it is good practice to set its value to
nullptr immediately after delete has been called on it.
• This will make it clear to the rest of the program that the pointer no longer
refers to a valid memory location.
• It also avoids problems that can arise from calling delete more than once on the
same pointer.
• If you set the pointer to null, then there's no double deletion problem because
delete is designed to do nothing when called on a null pointer.
Dangling Pointers
• A pointer is said to be dangling if it is pointing
to a memory location that has been freed by a
call to delete.
• When you access a dangling pointer, you are
trying to use memory that has already been
freed and returned to the heap
• Such memory may already be reallocated by
another call to new.
Avoiding dangling pointers (2 rules)
1. Set pointers to null as soon as their
memory is freed
2. Verify that a pointer is not null before you
attempt to access its memory
Memory Leaks
• A memory leak is said to occur in your program if,
after you have finished using a block of memory
allocated by new, you forget to free it via delete.
• The leaked block of memory remains unavailable
for use until the program terminates.
• Memory leaks are especially serious when they
occur in loops.
Memory Leaks
• They are even more serious in programs such as Web servers and
other network programs that are expected to run for months or even
years without being shut down.
• Over time, a Web server with a memory leak will exhaust all
memory in the computer on which it is running, requiring both it
and the computer to be shut down and restarted.
Warning
• Only use pointers with delete that were
previously used with new.
• If you use a pointer with delete that does not
reference dynamically allocated memory,
unexpected problems could result!
double *sales = nullptr, total = 0.0, average;
int numDays;
cout << "How many days of sales figures do you wish ";
cout << "to process? ";
cin >> numDays;
sales = new double[numDays]; // Allocate memory
cout << "Enter the sales figures below.\n";
for (int count = 0; count < numDays; count++) for (int count = 0; count < numDays; count++)
{ {
cout << "Day " << (count + 1) << ": "; total += sales[count];
cin >> sales[count]; }
}
average = total / numDays;
cout << setprecision(2) << fixed << showpoint;
cout << "\n\nTotal Sales: $" << total << endl;
cout << "Average Sales: $" << average << endl;
delete [] sales;
sales = nullptr;
There are two rules of thumb that are helpful
when trying to avoid memory leaks:
• Whenever possible, the function that invokes new to allocate storage
should also be the function that invokes delete to deallocate the storage.
• A class that needs to dynamically allocate storage should invoke new in its
constructors and invoke the corresponding delete in its destructor.
• Because the destructor is automatically called by the system whenever an
object is deleted or goes out of scope, a delete statement placed in a
destructor will always be called.
class Squares
{ void outputSquares(Squares *sqPtr)
private:
int length; // How long is the sequence {
int *sq; // Dynamically allocated array cout << "The list of squares is: ";
public: sqPtr->print();
Squares(int len)
{
length = len; }
sq = new int[length];
for (int k = 0; k < length; k++) int main()
{ {
sq[k] = (k+1)*(k+1);
} // allocates Squares object
cout << "Construct an object of size " << length << endl; Squares *sqPtr = new Squares(3);
} outputSquares(sqPtr);
void print()
{
for (int k = 0; k < length; k++) // Main deallocates Sq object
cout << sq[k] << " "; delete sqPtr;
cout << endl;
}
return 0;
~Squares()
{ }
delete [ ] sq;
// Trace
cout << "Destroy object of size " << length << endl;
} };
Concept
Pointers and dynamic memory allocation can be
used with class objects
Declaring a pointer to a class (same as
declaring any other pointer type)
Assume we have a Rectangle class:
class Rectangle
{
int width, height;
};
class Rectangle
{ Pointers to a class
int width, height;
};
Rectangle *pRect = nullptr; // Pointer to Rectangle
Rectangle rect; // Rectangle object
pRect = ▭ // Assign address of rect to pRect
class Rectangle
{
int width, height;
Dot selector error
};
Rectangle *pRect = nullptr;
Rectangle rect;
pRect = ▭
*pRect.width 🡨 Might assume this is how to access member
variables of the rect class…but…
class Rectangle
{
int width, height;
Dot selector error
};
Rectangle *pRect = nullptr;
Rectangle rect;
pRect = ▭
*pRect.width 🡨 dot selector has higher priority than *
So *pRect.width is equal to *(pRect.width)
class Rectangle
{
int width, height;
Error fixed
};
Rectangle *pRect = nullptr;
Rectangle rect;
pRect = ▭
(*pRect).width 🡨 Now * is performed before .
class Rectangle
{
int width, height;
Member variables set
};
Rectangle *pRect = nullptr;
Rectangle rect;
pRect = ▭
(*pRect).width = 10;
(*pRect).height = 20;
class Rectangle
{
int width, height;
Confusing syntax?
};
(*pRect).width = 10; 🡪 pRect−>width = 10;
Use of parentheses, the indirection operator, and the dot selector to access members
of class objects via pointers can result in expressions that are hard to read.
To solve this problem, C++ provides the structure pointer operator −> to use when
you want to access a member of a class object through a pointer.
class Rectangle
{ Dynamic Allocation of Class Objects
int width, height;
};
Local allocation Dynamic allocation
Rectangle *pRect = nullptr; pRect = new Rectangle;
pRect -> width = 10;
Rectangle rect; pRect -> height = 3;
pRect = ▭ or w/constructor
pRect -> width = 10; pRect = new Rectangle(10,30);
class Person
{
private:
string name;
int age;
public:
Person(string name1, int age1)
{
name = name1;
age = age1;
}
int getAge() { return age; }
string getName() { return name; }
};
struct Rectangle
{
int width, height;
};
Rectangle *pRect = nullptr; // Pointer to Rectangle
Person *pPerson = nullptr; // Pointer to Person
// Local object accessed through a pointer
Rectangle rect;
pRect = ▭
(*pRect).height = 12;
pRect->width = 10;
cout << "Area of the first rectangle is "
<< pRect->width * pRect->height;
// Dynamically allocated object accessed through pointer
pRect = new Rectangle;
pRect->height = 6;
pRect->width = 5;
cout << "\nArea of the second rectangle is " << pRect->width * pRect->height;
delete pRect;
pRect = nullptr;
// Dynamically allocated object accessed through pointer
pPerson = new Person("Miquel E. Gonzalez", 23);
cout << "\n\nThe person's name is " << pPerson->getName();
cout << "\nThe person's age is " << pPerson->getAge() << endl;
delete pPerson;
pPerson = nullptr;