Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Решенные оветы на теорию Си.docx
Скачиваний:
4
Добавлен:
01.03.2025
Размер:
167 Кб
Скачать
☆

__Gc arrays

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

int ar __gc[] = new int __gc[10];

ar[0] = 1;

ar = new int __gc[20];

Создать массив объектов Foo можно следующим образом

Foo *ar[] = new Foo*[10];

ar[0] = new Foo;

Как вы можете заметить, в примере с объектом Foo мы не использовали ключевого слова __gc. В этом нет необходимости, так как компилятор уже знает, что имеет дело с управляемым типом.

Для возвращения массивов из функций и для объявления многомерных массивов в MC++ также применяется новый причудливый синтаксис:

int test() __gc[]

{

return new int __gc[10];

}

void test()

{

int ar __gc[,] = new int __gc[10,20];

for (int i=0; i<ar->GetLength(0); i++)

for (int j=0; j<ar->GetLength(1); j++)

ar[i,j] = i + j;

}

Из последнего примера явно следует, что управляемые массивы не являются привычными для нас массивами C++. Скорее, это объекты со своим интерфейсом, и, к сожалению, мы не можем применять для них обычные в C++ методы работы с массивами. Это легко проверить на следующем примере:

void test()

{

int ar __gc[] = new int __gc[10];

int *p1 = ar; // ошибка

int *p2 = &ar[0]; // ошибка

}

__pin

Тем не менее, было бы странным не иметь доступа к памяти управляемых объектов. И такая возможность есть. Managed Extensions for C++ включает ещё одно ключевое слово - __pin, позволяющее объявлять pinning pointers на управляемые объекты. Один из переводов этого термина мог бы звучать, как “прикольные указатели”, но боюсь, что это может быть неправильно понято. Поэтому мы будем пользоваться оригиналом или, в крайнем случае, транслитерацией.

Pin-указатели позволяют зафиксировать объект в памяти и сделать его неперемещаемым до тех пор, пока такой указатель существует как объект и его значение не равно нулю. Рассмотрим пример:

void test()

{

int ar __gc[] = new int __gc[10];

int __pin *p = &ar[0];

memset(p-100,-1,2000); // делаем, что хотим

}

__nogc

Как нетрудно догадаться, это ключевое слово обозначает обычный неуправляемый тип C++. Этот модификатор используется компилятором по умолчанию и приведён здесь лишь для полноты картины.

__Value

Согласитесь, размещать абсолютно все переменные в управляемой куче расточительно, особенно если это просто байт или целое, использующиеся в качестве счётчика. Как известно, размещение переменных в стеке является наиболее эффективным для простых переменных с коротким жизненным циклом. Идентификатор __value позволяет объявлять управляемые типы, которые, в отличие от gc-типов, могут размещаться как в управляемой куче, так и в стеке программы. В таблице 1 приведено соответствие между примитивными типами C++ и управляемыми типами CLR.

С помощью модификатора __value можно объявлять как классы и структуры, так и управляемые перечислимые типы. Более того, это единственный способ объявлять перечисления, которые будет понимать CLR. Например:

__value class cl { int a; };

__value struct st { int a; };

__value enum en : int { En1, En2 };

__box

Ключевое слово __box создаёт обёртку для value-типов, после чего их можно использовать так же, как и gc-классы. Такие языки, как C# и VB.NET, создают обёртки для value-типов автоматически, в MC++ неявное преобразование запрещено из соображений производительности.

using namespace System::Collections;

void test()

{

Stack *s = new Stack();

int i = 1;

s->Push(i); // ошибка

s->Push(__box(i)); // ok

}