На этом шаге мы рассмотрим еще один способ задания массивов.
В языке C++ наряду с обычным объявлением массива в виде "тип Имя[размерность]" (native-массивы) можно объявить массив, пользуясь ключевым словом array (managed-массивы). Этот массив будет располагаться в выделенной средой CLR памяти.
Синтаксис объявления такого массива следующий:
[qualifiers] [cli::]array <[qualifiers]type1[, dimension]>^ var = gcnew [cli::] array<type2[, dimension]>(val[,val...])
Здесь:
Квалификатор mutable, например, означает, что если массив имеет такой квалификатор и является членом класса, то ему может присваивать значения функция (тоже член класса), у которой есть квалификатор const. В объявлении массива этого типа присутствует утилита gcnew, которая сразу же в объявлении выделяет под экземпляр массива CLR-память.
Пример работы с рассмотренным массивом приведен ниже, а результат - на рисунке 1. Пояснения к тексту программы даны в самом тексте.
// 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++.