На этом шаге мы рассмотрим еще один способ задания массивов.
В языке C++ наряду с обычным объявлением массива в виде "тип Имя[размерность]" (native-массивы) можно объявить
массив, пользуясь ключевым словом array (managed-массивы). Этот массив будет располагаться в выделенной средой CLR памяти.
Синтаксис объявления такого массива следующий:
[qualifiers] [cli::]array <[qualifiers]type1[, dimension]>^ var = gcnew [cli::] array<type2[, dimension]>(val[,val...])
Здесь:
- dimension - размерность массива. По умолчанию размерность массива равна 1 (одномерный массив). Максимальная размерность
равна 32; - val - количество элементов массива;
- qualifiers - спецификатор класса памяти. Значениями этого параметра могут быть: mutable, volatile, const, extern и static.
Квалификатор mutable, например, означает, что если массив имеет такой квалификатор и является членом класса, то ему может присваивать
значения функция (тоже член класса), у которой есть квалификатор const. В объявлении массива этого типа присутствует утилита gcnew,
которая сразу же в объявлении выделяет под экземпляр массива CLR-память.
Пример работы с рассмотренным массивом приведен ниже, а результат - на рисунке 1. Пояснения к тексту программы даны в самом тексте.
Примечание.
Все что мы рассматривали ранее, касающееся структур, классов и массивов, не предназначенных для работы в среде CLR, намеренно
сохрнено на тот случай, если пользователю придется обращаться к более ранним средам.
// 80_1.cpp: главный файл проекта. #include "stdafx.h" // compile with: /clr using namespace System; //этот оператор подключается в заголовку //автоматически, когда вы задаете CLR-шаблон //консольного приложения #define ARRAY_SIZE 2 value struct MyStruct //managed-value-структура { int m_i; }; ref class MyClass // managed-ref-класс { public: int m_i; }; struct MyNativeClass //native-структура { int m_i; }; //Эта функция возвращает массив ссылочного типа (массив ссылок): array <MyClass^>^ Test0() // <MyClass^> - тип массива: ссылки на объекты класса { int i; //объявление массива с именем local[] (это массив ссылок на объекты класса): array< MyClass^ >^ local = gcnew array< MyClass^ >(ARRAY_SIZE); for (i = 0 ; i < ARRAY_SIZE ; i++) { //Для каждого элемента массива надо создать экземпляр класса MyClass, //чтобы получить доступ к члену этого класса: local[i] = gcnew MyClass; //возвращает ссылку на выделенную память local[i] -> m_i = i; //члену экземпляра класса MyClass m_i //присваивается значение i } return local; //возвращается массив ссылок на созданные объекты класса } //Функция возвращает массив целых чисел типа Int32. array<Int32>^ Test1() //<Int32> - тип массива { int i; //объявление массива с именем local[] (это массив ссылок на числа типа Int32): array < Int32 >^ local = gcnew array< Int32 > (ARRAY_SIZE); for (i = 0 ; i < ARRAY_SIZE ; i++) local[i] = i + 10; return local; } //Функция модифицирует массив, т.к. через указатели это можно //делать с внешними переменными: void Test2 (array< MyNativeClass * >^ local) { for (int i = 0 ; i < ARRAY_SIZE ; i++) local[i] -> m_i = local[i] -> m_i + 2; } void main() { int i; //Объявляется массив MyClass() и инициализируется функцией TestO(): //происходит присвоение значений одного массива значениям //другого массива, т. к. массивы идентичны по построению array < MyClass^ >^ MyClass0; MyClass0 = Test0(); //Вывод значений массива на экран for (i = 0 ; i < ARRAY_SIZE ; i++) Console::WriteLine("MyClass0[{0}] = {1}", i, MyClass0[i] -> m_i); Console::WriteLine(); //Объявляется массив чисел IntArray[] и инициализируется функцией Test1(): array < Int32 >^ IntArray; IntArray = Test1(); //Вывод значений массива на экран for (i = 0 ; i < ARRAY_SIZE ; i++) Console::WriteLine("IntArray[{0}] = {1}", i, IntArray[i]); Console::WriteLine(); //Объявляется и инициализируется массив MyClass1: array < MyClass^ >^ MyClass1 = gcnew array< MyClass^ >(ARRAY_SIZE); for (i = 0 ; i < ARRAY_SIZE ; i++) { MyClass1[i] = gcnew MyClass; MyClass1[i] -> m_i = i + 20; } //Вывод значений массива на экран for (i = 0 ; i < ARRAY_SIZE ; i++) Console::WriteLine("MyClass1[{0}] = {1}", i, MyClass1[i] -> m_i); Console::WriteLine(); //Объявляется массив обычных указателей и инициализируется: array < MyNativeClass * >^ MyClass2 = gcnew array<MyNativeClass * >(ARRAY_SIZE); for (i = 0 ; i < ARRAY_SIZE ; i++) { //Обратите внимание, что вместо утилиты gcnew применяется new, //т. к. последняя утилита работает с нормальными указателями, //задаваемыми символами "*", //a gcnew - с указателями среды CLR, задаваемыми символом "^*" MyClass2[i] = new MyNativeClass() ; MyClass2[i] -> m_i = i + 30; } //Вывод значений массива на экран for (i = 0 ; i < ARRAY_SIZE ; i++) Console::WriteLine("MyClass2[{0}] = {1}", i, MyClass2[i]->m_i); Console::WriteLine(); //Модификация массива и вывод значений на экран Test2(MyClass2); for (i = 0 ; i < ARRAY_SIZE ; i++) Console::WriteLine("MyClass2[{0}] = {1}", i, MyClass2[i]->m_i); Console::WriteLine(); //Удаление массивов после применения оператора new //(среда CLR сама освобождает память): delete [] MyClass2[0]; delete [] MyClass2[1]; //Использование конструктора класса array < MyStruct >^ MyStruct1 = gcnew array< MyStruct >(ARRAY_SIZE); for (i = 0 ; i < ARRAY_SIZE ; i++) { //модификация элементов класса MyStruct1[i] = MyStruct(); //Конструктор класса создает экземпляр класса MyStruct1[i].m_i = i + 40; } //Вывод значений массива на экран for (i = 0 ; i < ARRAY_SIZE ; i++) Console::WriteLine("MyStruct1[{0}] = {1}", i, MyStruct1[i].m_i); Console::ReadLine(); //для задержки экрана }
Архив проекта можно взять здесь.
Результат работы приложения:
Рис.1. Результат работы приложения
Со следующего шага мы начнем рассматривать ввод и вывод в языках C и C++.