C++ Linked Lists   «Prev  Next»
Lesson 2A "safe" array
ObjectiveExamine the implementation of a safe array class that eliminates out-of-bounds errors.

C++ safe array Implementation

The one-dimensional array in C++ is a very useful aggregate type. In many ways, it is the prototypical container--easy to use and highly efficient. However, it is error prone. A common mistake is to access elements that are out of bounds. C++ allows us to control this problem by defining an analogous container type in which bounds can be tested. Here is a "safe" array class called vect:

//Implementation of a safe array type vect
class vect {
public:
explicit vect(int n = 10);
~vect() { delete []p; }
int& element(int i);        //access p[i]
int  ub() const {return (size - 1);}  //upper bound
private:
int*  p;
int   size;
};

vect::vect(int n) : size(n)
{
assert(n > 0);
p = new int[size];
assert(p);
}

The constructor

The constructor vect::vect(int n) allows the user to build dynamically allocated arrays.
We declare the constructor explicit because it is not intended as an implicit conversion from int to vect. Such arrays are much more flexible than those in languages such as Pascal and C, in which array sizes must be constant expressions. The constructor also initializes the variable size, whose value is the number of elements in the array.

int& vect::element(int i)
{
assert (i >= 0 && i < size);
return p[i];
}

C++ safe indexing member function

Access to individual elements is through the safe indexing member function:
int& vect::element(int i)
{
   assert (i >= 0 && i < size);
   return p[i];
}

An index that is outside the expected array range 0 through ub will cause an assertion failure. This safe indexing member function returns a reference to int that is the address of p[i] and that can be used as the lvalue of an assignment. This technique is often used in C++, and will be an efficient mechanism for operating on complicated types.
For example, the declarations
vect a(10), b(5);

construct an array of ten integers and an array of five integers, respectively. Individual elements can be accessed by the member function element, which checks whether the index is out of range. The statements
a.element(1) = 5;
b.element(1) = a.element(1) + 7;
cout << a.element(1) - 2;

are all legal. In effect we have a safe dynamic array type.
Classes with default constructors use them to initialize a derived array type. For example,
vect a[5];

is a declaration that uses the default constructor to create an array a of five objects, each of which is a size 10 vect. The ith element's address in the jth array would be given by a[j].element(i).

SEMrush Software