pointers, variables, and memory. variables and pointers when you declare a variable, memory is...
TRANSCRIPT
Pointers, Variables, and Memory
Variables and Pointers
When you declare a variable, memory is allocated to store a value. A pointer can be used to hold the address to a chunk of memory.
The operator & is used to return a variable’s memory address
int intVar; // allocate memory by // declaring a variable
cout << "Address = " << &intVar << endl;
Variables and Pointers
A pointer variable is used to hold an address to a memory location. A pointer variable has a type associated with it, and the memory address it points to, should hold data of that type
int myInt = 0; // Allocates memory, stores 0
int *pMyInt; // Declares an empty pointer // variable
Dereferencing Pointers
If we want to set or get the value that is stored at the memory address in the pointer then we have to use operator*
int myInt = 0; //Allocates memory, stores 0int *pMyInt; //Declares an empty pointerpMyInt = &myInt; //Puts address in the ptr
variable name
myIntpMyInt
300030043008
03004
valuememory address
3012
Dereferencing Pointers
If we want to set or get the value that is stored at the memory address in the pointer then we have to use operator*int myInt = 0; //Allocates memory, stores 0
int *pMyInt; //Declares an empty pointer
pMyInt = &myInt; //Puts address in the ptr
*pMyInt = 5; //puts 5 into myInt
variable name
myIntpMyInt
300030043008
53004
valuememory address
3012
Dereferencing Pointers
If we want to set or get the value that is stored at the memory address in the pointer then we have to use operator*
int myInt = 0; //Allocates memory, stores 0
int *pMyInt; //Declares an empty pointer
pMyInt = &myInt; //Puts address in the ptr
*pMyInt = 5; //puts 5 into myInt
cout << myInt << endl; //Prints 5
cout << *pMyInt << endl; //Also prints 5
cout << pMyInt << endl; //What prints?variable name
myIntpMyInt
300030043008
53004
valuememory address
3012
Where are the errors?
int main(){
int m; int *pm; *pm = 5;
int n; int *pn = &n; pn = 5;
}
Where are the errors?
int main(){
int m; int *pm; *pm = 5;
int n; int *pn = &n; pn = 5;
}
ERROR! No address in pm//Correctionpm = &m;*pm = 5;
Where are the errors?
int main(){
int m; int *pm; *pm = 5;
int n; int *pn = &n; pn = 5;
}
ERROR! No address in pm//Correctionpm = &m;*pm = 5;
ERROR! Missing operator*//Correction*pn = 5;
Pointers & Arrays
Pointers are simply, by definition, variables that hold addresses. A name of an array also holds the address of the first element in the array. This value cannot change. Therefore, an array name can be considered to be a pointer constant.
Pointers & Arrays
const int CAPACITY = 5;
int myArray[CAPACITY]; //Declare an arraycout << myArray; //Prints its addressfor( int i=0; i<CAPACITY; ++i ) myArray[i] = i; //initialize the elementscout << *myArray << endl; //Prints 0cout << myArray[0] << endl; //Prints 0
0 1 2 3 40 1 2 3 4
myArray
Pointer Arithmetic
Pointer arithmetic allows a few arithmetic operators for manipulating the addresses in pointers. In an array a, a is a constant pointer to the first element and a+1 is a constant to the second element. In the same way, if p points to the second element in an array, then p-1 point to the preceding element in that array, and p+1 points to the succeeding element.
Pointer Arithmetic
int a[5] = {2, 4, 6, 8, 10};int *p;p = &a[1];cout << a[0] << ", " << p[-1]<< ", " << *(p - 1) << endl;cout << a[1] << ", " <<p[0]<< ", " << *(p) << endl;cout << a[2] << ", " << p[1]<< ", " << *(p + 1) << endl;
Output: 2, 2, 2 4, 4, 4
6, 6, 6
Incrementing and Decrementing Addresses with Postfix and Prefix Operators
Adding 1 to a pointer causes the pointer to point to the next element of the type being pointed to. Therefore p++ should point to the next element.However, when a combination of indirection and postfix operators are used ( as is often done), use the precedence table to figure out what gets executed first. Postfix operators have higher precedence than the indirection operator.
Incrementing and Decrementing Addresses with Postfix and Prefix Operators
int *p;int a[5] = {12, 4, 16, 98, 50};p = a;cout << (*p)++ << endl; // prints 12cout << *p << endl; // print 4cout << *++p << endl; // prints 16cout << *p << endl; // prints 16cout << (*p)-- << endl; // prints 16cout << *p << endl; // prints 4cout << *--p << endl; // prints 12cout << *p << endl; // prints 12
Is this the same as *p++?
Is this the same as *(--p) ?
Dynamically Allocating Arrays
An array can be created “dynamically” with “new” “new” allocates a section of memory for the array, and then returns
a pointer to it. This is a major advantage when you don’t know how large the array
will be until the program is running
int capacity, *myData;cin >> capacity;myData = new int[capacity];//Creates the arrayfor( int i=0; i<capacity; ++i ) //Initialize it myData[i] = i;cout << myData[0] << endl; //Prints 0delete [] myData;
Using delete
Memory allocated with “new” must always be recovered by “delete”
Always “delete” an array when you don’t need it anymore if you created it with “new”
delete [] myData;
Function Arguments
The variables that are used to pass data into a function or to return results
Examplebool isPalindrome( string forw, string rev ){if( forw == rev ) return true;
}
Arguments can be passed– By value – the default in C++– By reference
arguments or parametersfunctionname
returntype
Passing Arguments by Value
Used to pass data only into a function When a variable is passed by value, a copy of it is made inside the
function. The copy is destroyed when the function returns. Example: passing an argument by value
void noChange( int n ){n = n + n;
}
int main() {int num = 5;noChange( num );cout << num << endl; //prints 5
}
Reference Argument
Syntaxint &count
Indicates that an alias for the argument is used inside the function
Using References
Used primarily for function arguments to implement “passing by reference”
Advantage: Efficiency– Passing variables to functions by reference is very
useful if you want to change or update a variable through a function.
– If your variable is a relatively large variable, or a whole class or struct or array, it is always advisable to pass the variable by reference since big amounts of data need not be copied when evaluating them.
Passing Arguments by Reference
#include <iostream> void Square(int &pVal);
main() { int Number=10; printf("Number is %d\n", Number); Square(Number); printf("Number is %d\n", Number);
}
void Square(int &pVal) { pVal *= pVal; printf("Number is %d\n", pVal);
}
Passing Arguments by Pointer
#include <iostream> void Square(int *pVal);
main() { int Number=10; printf("Number is %d\n", Number); Square(&Number); printf("Number is %d\n", Number);
}
void Square(int *pVal) { *pVal *= *pVal; printf("Number is %d\n", *pVal);
}
Reference vs. Pointers
References cannot be re-assigned. They are like constant pointers.
A good rule of the thumb is to use references when you can, and pointers when you ‘have to’
Passing an Array to a Function
Since an array name is actually a pointer to its first element, when an array is passed to a function, an address operator is not needed.
int findMax ( int [], int );int main(){
int a[5] = {12, 4, 16, 98, 50};cout << "The maximum value is " << findMax(a, 5) << endl;return 1;
}int findMax ( int vals[], int numElem ){
int max = vals[0];for (int i=1; i<numElem; i++ )
if (max < vals[i] )max = vals[i];
return max;}
Passing an Array to a Function
However, since an address is actually passed, the code can also be written thus:
int findMax ( int [], int );int main(){
int a[5] = {12, 4, 16, 98, 50};cout << "The maximum value is " << findMax(a, 5) << endl;return 1;
}int findMax ( int *vals, int numElem ){
int max = vals[0];for (int i=1; i<numElem; i++ )
if (max < vals[i] )max = vals[i];
return max;}
Passing an Array to a Function
Here are two other versions of findMax, this time using pointers instead of array subscripts:
int findMax ( int *vals, int numElem )
{
int max = *vals;
for (int i=1; i<numElem; i++ )
if (max < *(vals + i) )
max = *(vals + i);
return max;
}
Passing an Array to a Function
int findMax ( int *vals, int numElem ){
int max = *vals++; // gets the first element and// then increments
for (int i=1; i<numElem; i++, vals++ )if (max < *vals )
max = *vals;return max;
}
Dynamically Allocated structs
We can dynamically create a structure with “new”
Use “new” to allocate memory and return a pointer
Person *pDonald = new Person;
When a pointer is used to set values stored in a structure, each field must be accessed by the “->” operator
pDonald->ID = 1005;pDonald->firstName = "Donald";pDonald->lastName = "Knuth";cout << pDonald->firstName << endl; delete pDonald;//Always delete after new
Optional syntax: cout << (*pDonald).firstName;
Dynamic Memory Allocation
Data structures that use arrays, structs, and objects to store their data often use dynamic memory allocation to create the storage space
More efficient– We don’t need to know in advance how much space to set
aside
– Pointers can be passed to functions more efficiently because pointer parameters are passed by reference
Struct Constructors
Creating a structure that initializes itselfstruct Person{ int ID;
string name; Person(int i = 0000, string n = "Adam") : ID(i), name(n) { }};
Constructor is called whenever a Person is declared
Person adam;//Default values usedcout << adam.name << endl;//Prints AdamPerson david(1002,"David");//Arguments usedPerson *pFrank = new Person;//Default values usedpFrank->name = "Frank";
Initializer list
Default valueParameter
Constructorname