Learn C++ - C++ Pointer






The following code uses the & operator to find addresses.


#include <iostream> 
using namespace std; 
int main() /* w w  w  .j  a  va  2s  .  c o  m*/
{ 
     int donuts = 6; 
     double cups = 4.5; 

     cout << "donuts value = " << donuts; 
     cout << " and donuts address = " << &donuts << endl; 

     cout << "cups value = " << cups; 
     cout << " and cups address = " << &cups << endl; 
     return 0; 
} 

The code above generates the following result.





Example

The name of the pointer represents the location.

Applying the * operator yields the value at the location.


#include <iostream> 
int main() /* w  w  w .j  a  v  a2 s  .  com*/
{ 
     using namespace std; 
     int updates = 6;        // declare a variable 
     int * p_updates;        // declare pointer to an int 
     p_updates = &updates;   // assign address of int to pointer 

     // express values two ways 
     cout << "Values: updates = " << updates; 
     cout << ", *p_updates = " << *p_updates << endl; 

     // express address two ways 
     cout << "Addresses: &updates = " << &updates; 
     cout << ", p_updates = " << p_updates << endl; 

     // use pointer to change value 
     *p_updates = *p_updates + 1; 
     cout << "Now updates = " << updates << endl; 
     return 0; 
} 

The code above generates the following result.





Declaring and Initializing Pointers

A pointer declaration must specify what type of data to which the pointer points.

For example, the preceding example has this declaration:

int * p_updates;

This states that the combination * p_updates is type int.

The p_updates variable itself must be a pointer.

p_updates points to type int.

The type for p_updates is pointer-to-int or, more concisely, int *.

p_updates is a pointer (an address), and *p_updates is an int and not a pointer.

int* is a type, pointer-to-int.

The following declaration creates one pointer (p1) and one ordinary int (p2):

int* p1, p2;

You need an * for each pointer variable name.

The following code demonstrates how to initialize a pointer to an address.


#include <iostream> 
using namespace std; 
int main() //w  w w . java2  s .co  m
{ 
     int higgens = 5; 
     int * pt = &higgens; 

     cout << "Value of higgens = " << higgens 
           << "; Address of higgens = " << &higgens << endl; 
     cout << "Value of *pt = " << *pt 
           << "; Value of pt = " << pt << endl; 
     return 0; 
} 

The code above generates the following result.

Allocating Memory with new

The general form for obtaining and assigning memory for a single data object, which can be a structure as well as a fundamental type, is this:

typeName * pointer_name = new typeName;

You use the data type twice: once to specify the kind of memory requested and once to declare a suitable pointer.


#include <iostream> 
using namespace std; 
int main() /*w ww . j  a v a 2 s . c o  m*/
{ 
     int nights = 1001; 
     int * pt = new int;         // allocate space for an int 
     *pt = 1001;                 // store a value there 

     cout << "nights value = "; 
     cout << nights << ": location " << &nights << endl; 
     cout << "int "; 
     cout << "value = " << *pt << ": location = " << pt << endl; 
     double * pd = new double;   // allocate space for a double 
     *pd = 10000001.0;           // store a double there 

     cout << "double "; 
     cout << "value = " << *pd << ": location = " << pd << endl; 
     cout << "location of pointer pd: " << &pd << endl; 
     cout << "size of pt = " << sizeof(pt); 
     cout << ": size of *pt = " << sizeof(*pt) << endl; 
     cout << "size of pd = " << sizeof pd; 
     cout << ": size of *pd = " << sizeof(*pd) << endl; 
     return 0; 
} 

The code above generates the following result.

Freeing Memory with delete

The delete operator enables you to return memory to the memory pool.

You use delete by following it with a pointer to a block of memory originally allocated with new:

int * ps = new int; // allocate memory with new 
. . .               // use the memory 
delete ps;          // free memory with delete when done 

This removes the memory to which ps points.

It doesn't remove the pointer ps itself.

You can reuse ps to point to another new allocation.

You should not attempt to free a block of memory that you have previously freed.

Creating a Dynamic Array with new

It's easy to create a dynamic array in C++; you tell new the type of array element and number of elements you want.

The syntax requires that you follow the type name with the number of elements, in brackets.

For example, if you need an array of 10 ints, you use this:

int * psome = new int [10]; // get a block of 10 ints

The new operator returns the address of the first element of the block.

In this example, that value is assigned to the pointer psome.

Using new with brackets to create an array requires using an alternative form of delete when freeing the array:

delete [] psome;                  // free a dynamic array 

The brackets tells C++ to free the whole array, not just the element pointed to by the pointer.

Here's an example:

int * pt = new int; 
short * ps = new short [500]; 
delete [] pt;  // effect is undefined, don't do it 
delete ps;     // effect is undefined, don't do it 

Don't use delete to free memory that new didn't allocate.

Don't use delete to free the same block of memory twice in succession.

Use delete [] if you used new [] to allocate an array.

Use delete (no brackets) if you used new to allocate a single entity.

The general form for allocating and assigning memory for an array is this:

type_name * pointer_name = new type_name [num_elements]; 

Example


#include <iostream> 
using namespace std; 
int main() { /*from  w w  w  . ja v a2  s  .  com*/
     
     double * p3 = new double [3]; // space for 3 doubles 
     p3[0] = 0.2;                  // treat p3 like an array name 
     p3[1] = 0.5; 
     p3[2] = 0.8; 
     cout << "p3[1] is " << p3[1] << ".\n"; 
     p3 = p3 + 1;                  // increment the pointer 
     cout << "Now p3[0] is " << p3[0] << " and "; 
     cout << "p3[1] is " << p3[1] << ".\n"; 
     p3 = p3 - 1;                  // point back to beginning 
     delete [] p3;                 // free the memory 
     return 0; 
} 

The code above generates the following result.

Pointers, Arrays, and Pointer Arithmetic

C++ interprets the array name as an address.


#include <iostream> 
using namespace std; 
int main() { //w w w .j  av  a  2s  .c  om
     double wages[3] = {1.0, 2.0, 3.0}; 
     short stacks[3] = {3, 2, 1}; 

     // two ways to get the address of an array 
     double * pw = wages;     // name of an array = address 
     short * ps = &stacks[0]; // or use address operator 
     
     // with array element 
     cout << "pw = " << pw << ", *pw = " << *pw << endl; 
     pw = pw + 1; 
     //add 1 to the pw pointer 
     cout << "pw = " << pw << ", *pw = " << *pw << "\n\n"; 
     cout << "ps = " << ps << ", *ps = " << *ps << endl; 
     ps = ps + 1; 
     
     //add 1 to the ps pointer
     cout << "ps = " << ps << ", *ps = " << *ps << "\n\n"; 

     //access two elements with array notation
     cout << "stacks[0] = " << stacks[0] 
          << ", stacks[1] = " << stacks[1] << endl; 
     //access two elements with pointer notation
     cout << "*stacks = " << *stacks 
          << ", *(stacks + 1) =  " << *(stacks + 1) << endl; 

     cout << sizeof(wages) << " = size of wages array\n"; 
     cout << sizeof(pw) << " = size of pw pointer\n"; 
     return 0; 
} 

The code above generates the following result.

Pointers and Strings

The special relationship between arrays and pointers extends to C-style strings. Consider the following code:

char flower[10] = "rose"; 
cout << flower << "s are red\n"; 

The name of an array is the address of its first element.

The following code uses two functions from the string library.

The strlen() function returns the length of a string.

The strcpy() function copies a string from one location to another.


#include <iostream> 
#include <cstring>              // declare strlen(), strcpy() 
using namespace std; 
/*from  w  w  w .  ja v a  2  s.  co  m*/
int main() { 
     char animal[20] = "C++";   // animal holds bear 
     const char * bird = "Java"; // bird holds address of string 
     char * ps;                  // uninitialized 

     cout << animal << " and ";  // display bear 
     cout << bird << "\n";       // display wren 

     cout << "Enter a kind of animal: "; 
     cin >> animal;              // ok if input < 20 chars 

     ps = animal;                // set ps to point to string 
     cout << ps << "!\n";       // ok, same as using animal 

     //Before using strcpy()
     cout << animal << " at " << (int *) animal << endl; 
     cout << ps << " at " << (int *) ps << endl; 

     ps = new char[strlen(animal) + 1];  // get new storage 
     strcpy(ps, animal);         // copy string to new storage 
     cout << "After using strcpy():\n"; 
     cout << animal << " at " << (int *) animal << endl; 
     cout << ps << " at " << (int *) ps << endl; 
     delete [] ps; 
     return 0; 
} 

The code above generates the following result.

Example 3

The following code uses new to create an unnamed structure and demonstrates both pointer notations for accessing structure members.


#include <iostream> 
using namespace std; 
struct Product   // structure definition 
{ //from  ww w .  jav  a 2s  .c om
     char name[20]; 
     float volume; 
     double price; 
}; 
int main() {      
     Product * ps = new Product; // allot memory for structure 
     cout << "Enter name of Product item: "; 
     cin.get(ps->name, 20);            // method 1 for member access 
     cout << "Enter volume in cubic feet: "; 
     cin >> (*ps).volume;              // method 2 for member access 
     cout << "Enter price: $"; 
     cin >> ps->price; 
     cout << "Name: " << (*ps).name << endl;              // method 2 
     cout << "Volume: " << ps->volume << " cubic feet\n"; // method 1 
     cout << "Price: $" << ps->price << endl;             // method 1 
     delete ps;                        // free memory used by structure 
     return 0; 
} 

The code above generates the following result.

Example 4

The following code shows how to use the delete operator.


#include <iostream> 
#include <cstring>      // or string.h 
using namespace std; 
char * getname(void);   // function prototype 
int main() { 
     char * name;        // create pointer but no storage 
/*ww  w  . ja v  a 2s . c  o  m*/
     name = getname();   // assign address of string to name 
     cout << name << " at " << (int *) name << "\n"; 
     delete [] name;     // memory freed 

     name = getname();   // reuse freed memory 
     cout << name << " at " << (int *) name << "\n"; 
     delete [] name;     // memory freed again 
     return 0; 
} 
char * getname()        // return pointer to new string 
{ 
     char temp[80];      // temporary storage 
     cout << "Enter last name: "; 
     cin >> temp; 
     char * pn = new char[strlen(temp) + 1]; 
     strcpy(pn, temp);   // copy string into smaller space 

     return pn;          // temp lost when function ends 
} 

The code above generates the following result.