Объявление массивов в области динамического обмена

Существует возможность поместить весь массив в область динамического обмена. Для этого используется ключевое слово new и оператор индексирования, как показано в следующем примере, где результатом этой операции является указатель на массив, сохраненный в области динамического обмена:

CAT *Family = new CAT[500];

Указатель Family будет содержать адрес в динамической области первого элемента массива из пятисот объектов класса CAT. Другими словами, в указателе представлен адрес объекта Family[0].

Еще одно преимущество подобного объявления массива состоит в том, что в программе с переменной Family теперь можно будет выполнять математические действия как с любым другим указателем, что открывает дополнительные возможности в управлении доступом к элементам массива. Например, можно выполнить следующие действия:

CAT *Family = new CAT[500];

CAT *pCat = Family; // pCat указывает на Family[0]

pCat->SetAge(10); // присваивает Family[0] значение 10

pCat++; // переход к Family[1]

pCat->SetAge(20); // присваивает Family[1] значение 20

В данном примере объявляется новый массив из 500 объектов класса CAT и возвращается указатель на первый элемент этого массива. Затем, используя это указатель и метод SetAge(), объявленный в классе CAT, первому объекту массива присваивается

значение 10. Переход к следующему объекту массива осуществляется за счет приращения адреса в указателе на массив, после чего тем же способом присваивается значение 20 второму объекту массива.

Указатель на массив или массив указателей

Рассмотрим следующие три объявления:

1: Cat Family0ne[500];

2: CAT >> FamilyTwo[500];

3: CAT * FamilyThree = new CAT[500];

В первом случае объявляется массив FamilyOne, содержащий 500 объектов типа CAT. Во втором случае — массив FamilyTwo, содержащий 500 указателей на объекты класса CAT, и в третьем случае — указатель FamilyThree, ссылающийся на массив из 500 объектов класса CAT.

В зависимости от того, какое объявление используется в программе, принципиально меняются способы управления массивом. Как ни странно, но указатель FamilyThree по сути своей гораздо ближе к массиву FamilyOne, но принципиально отличается от массива указателей FamilyTwo.

Чтобы разобраться в этом, следует внимательно рассмотреть, что содержат в себе все эти переменные. Указатель на массив FamilyThree содержит адрес первого элемента массива, но ведь это именно то, что содержит имя массива FamilyOne.

Имена массивов и указателей

В C++ имя массива представляет собой константный указатель на первый элемент массива. Другими словами, в объявлении

CAT Family[50];

создается указатель Family на адрес первого элемента массива &Family[0].

В программе допускается использование имен массивов как константных указателей и наоборот. Таким образом, выражению Family + 4 соответствует обращение к пятому элементу массива Family[4].

Компилятор выполняет с именами массивов те же математические действия сложения, инкремента и декремента, что и с указателями. В результате операция Family + 4 будет означать не прибавление четырех байтов к текущему адресу, а сдвиг на четыре объекта. Если размер одного объекта равен четырем байтам, то к адресу в имени массива будут добавлены не 4, а 16 байт. Если в нашем примере каждый объект класса CAT содержит четыре переменные-члена типа long по четыре байта каждая и две переменные-члена типа short по два байта каждая, то размер одного элемента массива будет равен 20 байт и операция Family + 4 сдвинет адрес в имени указателя на 80 байт.

Объявление массива в динамической области памяти и его использование показано в листинге 12.7.

Листинг 12.7. Создание массива с использованием ключевого слова new

1: // Листинг 12.7. Массив в динамической области памяти

2:

3: #include <iostream.h>

4:

5: class CAT

6: {

7: public:

8: CAT() { itsAge = 1; itsWeight=5; }

9: ~CAT();

10: int GetAge() const { return itsAge; }

11: int GetWeight() const { return itsWeight; }

12: void SetAge(int age) { itsAge = age; }

13:

14: private:

15: int itsAgo;

16: int itsWeight;

17: };

18:

19: CAT::~CAT()

20: {

21: // cout << "Destructor called!\n";

22: }

23:

24: int main()

25: {

26: CAT * Family = new CAT[500];

27: int i;

28:

29: for (i = 0; i < 500; i++)

30: {

31: Family[i].SetAge(2*i +1);

32: }

33:

34: for (i = 0; i < 500; i++)

35: {

36: cout << "Cat #" << i+1 << ": ";

37: cout << Family[i].GetAge() << endl;

38: }

39:

40: delete [] Family;

41:

42: return 0;

43: }

Результат:

Cat #1: 1

Cat #2: 3

Cat #3: 5

...

Cat #499: 997

Cat #500: 999

Анализ: В строке 26 объявляется массив Family для пятисот объектов класса CAT. Благодаря использованию выражения new CAT[500] весь массив сохраняется в области динамической памяти.

Наши рекомендации