В отличие от массивов в обычном C++,
которые являются простым типом указателя,
управляемые массивы являются полноценными
управляемыми объектами, расположенными в
динамически распределяемой области. System: :
Array (Система::Массив) — абстрактный класс,
являющийся базовым для всех управляемых
массивов. Для определения неуправляемых
массивов можно использовать синтаксис
обычного C++; для определения же управляемых
массивов следует использовать либо
ключевое слово _дс (сборщик мусора), либо
указывать, что элементы массива относятся к
управляемому типу. Далее приведены примеры
определения массивов. Ключевое слово _дс (сборщик
мусора) и управляемые типы подробнее
рассмотрены ниже. Обратите внимание на две
//ArraySyntax.срр
fusing <mscorlib.dll>
using namespace System;
// использовать пространство имен
Система;
ttpragma warning(disable : 4101)
// уничтожить предупреждение о
переменной, на которую нет ссылки:
// предупреждение (отключить: 4101)
void main(void) {
// традиционный синтаксис
неуправляемого массива
int *pintUnManagedArrayOnHeap = new int [5];
int intUnManagedArray[5]; // нет ошибки для
неуправляемого
// массива
// синтаксис управляемого массива,
// используется ключевое слово _дс (сборщик
мусора) int intManagedArrayOnHeap _дс[] = new int _дс[5]; //int
intManagedArray _gc[5]; // ошибка для управляемого
// массива
// синтаксис управляемого массива,
используется
// управляемый тип элемента
String *strManagedArrayOnHeap[] = new String* [5]; //
Строка
//String *strManagedArray[5]; // ошибка для
управляемого
// массива }
Управляемые массивы имеют некоторые дополнительные, по сравнению с неуправляемыми массивами, свойства и ограничения.
Следующий пример показывает, как можно использовать обработчик исключений при попытке доступа к несуществующему элементу управляемого массива. Обратите внимание, что массив содержит пять элементов, а в цикле производится попытка установить значение шестого. Программа в обычном C++ выполнила бы такое действие, изменив содержимое памяти за пределами массива. Никто не скажет точно, чем это могло бы закончиться. При проверке корректности адреса выполняются два действия: во-первых, предотвращается изменение содержимого памяти за пределами массива; во-вторых, программе сообщается, что возникла подобная ситуация, тем самым давая возможность исправить ошибку еще на стадии тестирования. В обычном C++ такая ошибка часто не проявляется до тех пор, пока программа, по непонятным причинам, не прекращает работу, обычно в месте кода, далеко отстоящем от самой ошибки. И, разумеется, согласно закону Мэрфи, эта ошибка обнаруживается только тогда, когда программа уже передана заказчику. //IndexOutOfRangeException.срр
#using <mscorlib.dll> using namespace System;
// использовать пространство имен
Система/void main () {
int intArray _gc[]= new int _gc[5]; // сборщик
мусора [5]
for (int i=0; i<6; i++) // больше чем есть!!!
{
try {
intArray[i] = i; }
catch (IndexOutOfRangeException *piore) {
// нужно сделать кое-что более
полезное, // чтобы здесь восстановиться
Console::WriteLine("Oooops!"); Console::WriteLine(piore->get_Message());
} } }
Программа напечатает:
Oooops!
Exception of type System.IndexOutOfRangeException was thrown.
Перевод такой [Добавлен редактором русского перевода. — Прим. ред.]:
Возникло исключение типа Система.IndexOutOfRangeException.
Как и для неуправляемых массивов,
нумерация элементов в управляемых массивах
начинается с нуля. Однако, значения
элементов управляемых массивов, в отличие
от элементов неуправляемых массивов,
автоматически инициализируются значением,
принятым по умолчанию для каждого типа
элемента массива. Переменным примитивных
типов, таких, как int, char (символ), float (с
плавающей точкой) и double (с удвоенной
точностью) присваивается нуль. Элементам,
указывающим на управляемые объекты, также
по умолчанию присваивается нулевое
значение (т.е. нулевой указатель). Элементы
значимых типов инициализируются с помощью
их принятого по умолчанию конструктора (т.е.
конструктора, не имеющего аргументов).
Значимые типы подробнее рассмотрены ниже.
В следующем примере
иллюстрируется работа с массивами, и
сравниваются управляемый двумерный массив
и обычный неуправляемый двумерный же
массив. Обратите внимание, что при работе с
неуправляемым массивом используется
старый синтаксис доступа к элементам
массива [ ] [ ], тогда как при работе с
управляемым массивом, который является
истинно двумерным, используется синтаксис
[, ]. Хотя в этом примере при использовании
синтаксиса [ ] [ ] каждый из подмассивов имеет
одинаковое количество элементов, в других
случаях они могут иметь разные размеры (т.н.
массив с неровным правым краем). Синтаксис [,
] предполагает использование истинно
прямоугольного массива.
//Arrayl.срр
fusing <mscorlib.dll>
using namespace System;
// использовать пространство имен
Система;
void main () {
// управляемый одномерный массив int
// (использующий сборщик мусора)
Console::WriteLine("managed ID array of int");
// ("управляемый одномерный
массив int");
int intArray _gc[]= new int _gc[5];
for (int i=0; i<intArray->Length; i++)
{
intArray[i] = i;
Console::Write(intArray[i]); // Запись
Console::Write("\t"); // Запись }
Console::WriteLine();
// управляемый двумерный массив
Строк
// (использующий управляемый тип)
Console::WriteLine("managed 2D array of Strings");
// ("управляемый двумерный массив
Строк ");
String *str2DArray[,] = new String *[2,3]; // новая
Строка
for(int row=0; row<str2DArray->GetLength(0); row++)
//по строкам
{
for(int col=0; col<str2DArray->GetLength(l) ; col++)
//по столбцам
{
str2DArray[row,col] = (row*10 + col).ToString();
// str2DArray [строка, столбец] = (row*10 +
столбец)
// .ToString ();
Console::Write(str2DArray[row,col]);
// Запись:: (str2DArray [строка, столбец]);
Console::Write("\t"); // Запись }
Console::WriteLine(); }
// неуправляемый двумерный массив
int (для сравнения)
Console::WriteLine("unmanaged 2D array of int");
// ("неуправляемый двумерный
массив int");
int int2DArray[2][3];
for(int row=0; row<2; row++) //по строкам
{
for (int col=0; col<3; col++) // по столбцам {
int2DArray[row][col] = row*10 + col;
// int2DArray [строка] [столбец] = row*10 +
столбец; Console::Write(int2DArray[row][col]); // Запись::
(int2DArray [строка] [столбец]); Console::Write("\t"); //
Запись }
Console::WriteLine(); } )
Результат работы программы приведен ниже. Управляемый прямоугольный двумерный массив содержит элементы типа String*, а неуправляемый — элементы типа int. Однако управляемый массив может также содержать и элементы неуправляемых типов, между тем как неуправляемый массив — лишь элементы неуправляемых типов.
managed ID array of int 01234 managed 2D array of Strings 012
10 11 12
unmanaged 2D array of int
0 1 2
10 11 12
Перевод такой:
управляемый одномерный массив int
01234
управляемый двумерный массив Строк
0 1 2
10 11 12
неуправляемый двумерный массив int
0 1 2
10 11 12
Приведем еще один пример, в котором сравнивается использование массива массивов (синтаксис [ ] [ ]) и прямоугольного двумерного массива (синтаксис [, ]). На этот раз, ради более корректного сравнения, оба массива содержат элементы типа int.
//Array2.срр
#using <mscorlib.dll>
using namespace System;
// использовать пространство имен Система;
void main(void) {
Console::WriteLine("Rectangular array using [,]");
// ("Использование прямоугольного массива [,] ");
int rect2DArray [,] = new int _gc [3,41; // сборщик мусора -
// управляемый
for(int row=0; row< rect2DArray ->GetLength(0); row++) //
по строкам {
for(int col=0; col< rect2DArray->GetLength(1); col++)
// по столбцам
{
rect2DArray [row,col] = row*10 + col; // rect2DArray [строка,
столбец] = row*10 + столбец; Console : -.Write (rect2DArray [row, col] ) ; //
Запись:: (rect2DArray [строка, столбец]); Console::Write("\t"); //
Запись }
Console::WriteLine(); }
Console::WriteLine("Array of arrays using [][]"); //
("использование массива массивов [] [] "); int arrayOfArray[3][4];
// неуправляемый for(int row=0; row<3 ; row++) // по строкам {
for(int col=0; col<4; col++) // по столбцам {
arrayOfArray[row][col] = row*10 + col;
Добавлен редактором русского перевода. — Прим. ред.
// arrayOfArray [строка] [столбец] = row*10 + столбец; Console::Write(arrayOfArray[row][col]);
// Запись:: (arrayOfArray [строка] [столбец]); Console::Write("\t");
// Запись
}
Console::WriteLine(); } >
Программа напечатает:
Rectangular array using [,]
0 1 2 3
10 11 12 13
20 21 22 23
Array of arrays using [][]
0 1 2 3
10 11 12 13
20 21 22 23
Перевод такой:
Использование прямоугольного массива []
0 1 2 3
10 11 12 13
20 21 22 23
Использование массива массивов [] []
0 1 2 3
10 11 12 13
20 21 22 23
На рис. 3.1 и 3.2 показано размещение в памяти элементов массива массивов (объявленного с помощью синтаксиса [ ] [ ]) и прямоугольного двумерного массива (объявленного с помощью синтаксиса [, ]), использовавшихся в предыдущем примере.