Invoking the new operator secures a block of memory large enough to hold num_elements elements of type type_name, with pointer_name pointing to the first element. As you’re about to see, you can use pointer_name in many of the same ways you can use an array name.

Using a Dynamic Array

After you create a dynamic array, how do you use it? First, think about the problem conceptually. The following statement creates a pointer, psome, that points to the first element of a block of 10 int values:

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

Think of it as a finger pointing to that element. Suppose an int occupies 4 bytes. Then, by moving your finger 4 bytes in the correct direction, you can point to the second element. Altogether, there are 10 elements, which is the range over which you can move your finger. Thus, the new statement supplies you with all the information you need to identify every element in the block.

Now think about the problem practically. How do you access one of these elements? The first element is no problem. Because psome points to the first element of the array, *psome is the value of the first element. That leaves nine more elements to access. The simplest way to access the elements may surprise you if you haven’t worked with C: Just use the pointer as if it were an array name. That is, you can use psome[0] instead of *psome for the first element, psome[1] for the second element, and so on. It turns out to be very simple to use a pointer to access a dynamic array, even if it may not immediately be obvious why the method works. The reason you can do this is that C and C++ handle arrays internally by using pointers anyway. This near equivalence of arrays and pointers is one of the beauties of C and C++. (It’s also sometimes a problem, but that’s another story.) You’ll learn more about this equivalence in a moment. First, Listing 4.18 shows how you can use new to create a dynamic array and then use array notation to access the elements. It also points out a fundamental difference between a pointer and a true array name.

Listing 4.18. arraynew.cpp

// arraynew.cpp -- using the new operator for arrays

#include

int main()

{

    using namespace std;

    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;

}

Here is the output from the program in Listing 4.18:

p3[1] is 0.5.

Now p3[0] is 0.5 and p3[1] is 0.8.

As you can see, arraynew.cpp uses the pointer p3 as if it were the name of an array, with p3[0] as the first element, and so on. The fundamental difference between an array name and a pointer appears in the following line:

p3 = p3 + 1; // okay for pointers, wrong for array names

You can’t change the value of an array name. But a pointer is a variable, hence you can change its value. Note the effect of adding 1 to p3. The expression p3[0] now refers to the former second element of the array. Thus, adding 1 to p3 causes it to point to the second element instead of the first. Subtracting one takes the pointer back to its original value so that the program can provide delete [] with the correct address.

The actual addresses of consecutive ints typically differ by 2 or 4 bytes, so the fact that adding 1 to p3 gives the address of the next element suggests that there is something special about pointer arithmetic. There is.

Pointers, Arrays, and Pointer Arithmetic

The near equivalence of pointers and array names stems from pointer arithmetic and how C++ handles arrays internally. First, let’s check out the arithmetic. Adding one to an integer variable increases its value by one, but adding one to a pointer variable increases its value by the number of bytes of the type to which it points. Adding one to a pointer to double adds 8 to the numeric value on systems with 8-byte double, whereas adding one to a pointer-to-short adds two to the pointer value if short is 2 bytes. Listing 4.19 demonstrates this amazing point. It also shows a second important point: C++ interprets the array name as an address.

Listing 4.19. addpntrs.cpp

// addpntrs.cpp -- pointer addition

#include

int main()

{

    using namespace std;

    double wages[3] = {10000.0, 20000.0, 30000.0};

    short stacks[3] = {3, 2, 1};

// Here are 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;

    cout << "add 1 to the pw pointer:\n";

    cout << "pw = " << pw << ", *pw = " << *pw << "\n\n";

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги