A generic safe-array class that prevents array boundary errors.
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
template <class T, int len> class dyn_safe_array {
T *aptr;
int length;
public:
dyn_safe_array();
// copy constructor.
dyn_safe_array(const dyn_safe_array &obj);
// Release the allocated memory when a dyn_safe_array object goes out of scope.
~dyn_safe_array() {
delete [] aptr;
}
// Overload assignment.
dyn_safe_array &operator=(const dyn_safe_array<T,len> &rh_op);
// Use the subscripting operator to access elements in the safe array.
T &operator[](int i);
// Return the size of the array.
int getlen() { return length; }
};
// constructor.
template <class T, int len>
dyn_safe_array<T, len>::dyn_safe_array() {
try {
aptr = new T[len];
} catch(bad_alloc ba) {
cout << "Can't allocate array.\n";
// Take appropriate action here. This is just
// a placeholder response.
exit(1);
}
// Initialize the array elements to their default value.
for(int i=0; i < len; ++i) aptr[i] = T();
length = len;
}
// copy constructor.
template <class T, int len>
dyn_safe_array<T, len>::dyn_safe_array(const dyn_safe_array &obj) {
cout << "Using dyn_safe_array's copy constructor to make a copy.\n";
try {
aptr = new T[obj.length];
} catch(bad_alloc ba) {
cout << "Can't allocate array.\n";
exit(1);
}
length = obj.length;
// Copy contents of the array.
for(int i=0; i < length; ++i)
aptr[i] = obj.aptr[i];
}
// Overload assignment so that a copy of the array is made.
// The copy is stored in an allocated memory that is separate
// from that used by the right-hand operand.
template<class T, int len> dyn_safe_array<T, len> &
dyn_safe_array<T, len>::operator=(const dyn_safe_array<T, len> &rh_op) {
// If necessary, release the memory currently used by the object.
if(aptr && (length != rh_op.length)) {
// Delete the previously allocated memory.
delete aptr;
try {
// Allocate an array of the same size as the one used by rh_op.
aptr = new T[rh_op.length];
} catch(bad_alloc ba) {
// Take appropriate action here. This is just a placeholder response.
cout << "Can't allocate array.\n";
exit(1);
}
}
length = rh_op.length;
// Copy contents of the array.
for(int i=0; i < length; ++i)
aptr[i] = rh_op.aptr[i];
return *this;
}
template <class T, int len> T &dyn_safe_array<T, len>::operator[](int i)
{
if(i < 0 || i > length) {
cout << "\nIndex value of " << i << " is out-of-bounds.\n";
exit(1);
}
return aptr[i];
}
template <class T, int len>
dyn_safe_array<T, len> f(dyn_safe_array<T, len> x) {
cout << "f() is returning a copy of x.\n";
return x;
}
class myclass {
public:
int x;
myclass(int i) { x = i; };
myclass() { x = -1; }
};
int main()
{
// Use the integer array.
dyn_safe_array<int, 5> i_ar;
for(int i=0; i < i_ar.getlen(); ++i) i_ar[i] = i;
cout << "Contents of i_ar: ";
for(int i=0; i < i_ar.getlen(); ++i) cout << i_ar[i] << " ";
cout << "\n\n";
dyn_safe_array<int, 5> i_ar2 = i_ar;
for(int i=0; i < i_ar2.getlen(); ++i) cout << i_ar2[i] << " ";
dyn_safe_array<int, 5> i_ar3;
for(int i=0; i < i_ar3.getlen(); ++i) cout << i_ar3[i] << " ";
cout <<"\n\n";
i_ar3 = f(i_ar);
for(int i=0; i < i_ar3.getlen(); ++i) cout << i_ar3[i] << " ";
cout << "\n\n";
dyn_safe_array<myclass, 3> mc_ar;
cout << "Original contents of mc_ar: ";
for(int i=0; i < mc_ar.getlen(); ++i) cout << mc_ar[i].x << " ";
cout << endl;
mc_ar[0].x = 9;
mc_ar[1].x = 8;
mc_ar[2].x = 7;
for(int i=0; i < mc_ar.getlen(); ++i) cout << mc_ar[i].x << " ";
cout << "\n\n";
cout << " mc_ar2 = f(mc_ar);\n\n";
dyn_safe_array<myclass, 3> mc_ar2;
mc_ar2 = f(mc_ar);
cout << "Contents of mc_ar2 after receiving f(mc_ar): ";
for(int i=0; i < mc_ar2.getlen(); ++i) cout << mc_ar2[i].x << " ";
cout << endl;
return 0;
}
Related examples in the same category