А ещё всегда надо проверять в операторе присваивания, что объект не присваевается самому себе. В таком случае ничего делать не надо, иначе обычно просходит фигня типа копирования уже удалённой памяти и т.п.
Не соглашусь, что ничего не надо делать, надо вернуть себя.
Что-то вроде
if(this==&a) return *this.
И ещё по поводу оператора присваивания. Мне кажется, что нужно возвращать ссылку, т.е. прототип должен выглядеть как
Array &Array::operator =(const Array &a). Вроде бы это позволит трактовать результат как lvalue и пользоваться вкусными присваиваниями типа
a=b=c=d;
К тому же лучше в операторе присваивания и в копирующем конструкторе писать не
m[i] = a.m[i], а
m[i] = a[i] предварительно перегрузив оператор
[]. Кажется, желательно определить две его версии, одну как
Int &Array::operator [](unsigned long){...}, а другую как
const Int &Array::operator [](unsigned long) const {...}.
Кстати, при использовании класса
Array можно будет писать такие вещи как
Array array=5, и это скорее-всего будет корректным кодом (т.е. это эквивалентно
Array array=Array(5)). Однако в силу чрезвычайной ненаглядности подобных неявных преобразований рекомендуется помечать конструкторы с одним обязательным параметром ключевым словом
explicit.