Указатели. Часть 6. Составные native и managed типы данных. Управляемые указатели (^) в среде CLR. Выделение памяти. Квалификаторы ref и value. Управляемые указатели (^) на структуры и классы
Содержание
- 1. Какие особенности организации работы составных типов данных в среде CLR (Common Language Runtime)?
- 2. Какие особенности использования составных native типов данных?
- 3. Какие особенности использования управляемых (managed) составных типов данных?
- 4. Какие квалификаторы используются для объявления структур и классов в среде CLR?
- 5. Какое отличие между квалификаторами ref и value при объявлении структур или классов? Примеры доступа к ref-структурам и value-структурам с помощью указателя
- 6. Какой доступ по умолчанию имеют поля и члены данных структуры и класса?
- 7. Пример объявления и использования структуры с квалификатором ref
- 8. Каким образом описываются managed-массивы в среде CLR? Назначение ключевого слова array
- 9. Пример объявления и использования массива managed-структур, которые объявлены с квалификатором ref, с помощью управляемого указателя (^)
- 10. Пример объявления и использования managed-массива на базовые типы (int, double) с помощью управляемого (^) указателя
- 11. Пример объявления и использования массива указателей (^) на класс, которые объявленные как managed с использованием классификатора ref и ключевого слова array
- Связанные темы
Поиск на других ресурсах:
1. Какие особенности организации работы составных типов данных в среде CLR (Common Language Runtime)?
В языке C++ (Visual C++) существует два вида составных типов данных:
- native-типы данных. Указатели на такие типы данных обозначаются символом *;
- типы данных для работы в среде CLR (Common Language Runtime). Эти типы еще называются managed-типами данных или управляемыми типами данных. Такие типы данных размещаются в памяти, которая выделяется средой CLR. Объекты этих типов данных должны размещаться в динамической памяти, которая управляется средой CLR. Указатели на такую память обозначаются символом ^.
2. Какие особенности использования составных native типов данных?
К составным native-типам данных относятся:
- native-структуры;
- native-классы.
Для доступа к таким типам данных используется неуправляемый указатель * (unmanaged pointer).
Более подробно работа неуправляемых указателей (*) описывается в темах:
- Указатели. Часть 2. Неуправляемые указатели. Операции над указателями. Указатель на тип void. Выделение памяти. Нулевой указатель. Операция взятия адреса &.
- Указатели. Часть 3. Неуправляемые указатели и массивы. Указатель на структуру. Указатель на класс
- Указатели. Часть 5. Выделение памяти для указателя. Массивы указателей на базовые типы, структуры, функции, классы
3. Какие особенности использования управляемых (managed) составных типов данных?
К управляемым составным типам данных (managed) относятся:
- managed-структуры;
- managed-классы.
Такие структуры и классы предназначены для работы в среде CLR. Они размещаются в памяти, которая выделяется и управляется средой CLR. Если программист создает проект типа «CLR Console Application» или «Windows Forms Application», то этот проект удовлетворяет требованиям среды CLR.
Объекты, которые управляются CLR средой, попадают в управляемую динамическую память. При описании указателя на managed-структуру или managed-класс используется символ ^. Память для такого указателя выделяется утилитой gcnew.
4. Какие квалификаторы используются для объявления структур и классов в среде CLR?
В среде CLR структуры и классы могут иметь два квалификатора:
- квалификатор ref – означает, что структура или класс есть ссылочного типа;
- квалификатор value – означает, что структура или класс есть типом значения.
В среде CLR можно также объявлять структуру или класс без квалификатора. Работа с такими структурами используется для совместимости с указателями на структуры более старых версий C/C++.
5. Какое отличие между квалификаторами ref и value при объявлении структур или классов? Примеры доступа к ref-структурам и value-структурам с помощью указателя
Отличие между квалификаторами ref и value состоит в способе выделения памяти для указателя на структуру или класс.
С модификатором ref структура или класс размещается в управляемой (managed) куче и не может быть размещена в native-куче.
С модификатором value структура или класс может быть размещена и в управляемой (managed) куче и в native-куче.
Нижеследующие примеры демонстрируют отличие между структурами, которые описаны с квалификаторами ref и value. То же самое относится и к классам.
Пусть нужно использовать структуру, которая описывает пиксель на экране монитора.
Пример 1. Объявление структуры с квалификатором ref.
// структура объявлена с квалификатором ref ref struct MyPoint_ref { int x; int y; int color; };
Тогда, использование структуры из другого программного кода может быть следующим:
// Квалификатор ref // 1. Объявление указателя на структуру с квалификатором ref MyPoint_ref ^ pr; // 2. Выделение памяти для указателя // Память выделяется в управляемой (managed) "куче" pr = gcnew MyPoint_ref; // 3. Заполнение полей структуры pr->x = 28; pr->y = 35; pr->color = 2; // Ошибка! // MyPoint_ref * p; - невозможно описать неуправляемый указатель на ref-структуру
Пример 2. Объявление структуры с квалификатором value.
// структура объявлена с квалификатором value value struct MyPoint_value { int x; int y; int color; };
Использование структуры
// Квалификатор value // 1. Объявление указателей на структуру с квалификатором value MyPoint_value ^ p1; // managed-указатель MyPoint_value * p2; // native-указатель - также работает // 2. Выделение памяти для указателей p1 = gcnew MyPoint_value; p2 = new MyPoint_value; // 3. Демонстрация работы с полями структур через указатели p1->x = 33; p1->y = 200; p1->color = 3; p2->x = 10; p2->y = p1->y; p2->color = p1->color;
6. Какой доступ по умолчанию имеют поля и члены данных структуры и класса?
При объявлении структуры, ее поля (члены данных) и методы имеют спецификатор доступа public.
При объявлении класса, его члены данных и методы имеют спецификатор доступа private.
7. Пример объявления и использования структуры с квалификатором ref
Пусть дана структура, которая объявлена в модуле «MyRefStruct.h». Структура описывает координаты точки на плоскости. Структура объявлена с квалификатором ref.
ref struct MyPointRef { int x; int y; };
Пример использования структуры в программе с помощью управляемого (managed) указателя.
// объявление структуры с квалификатором ref MyPointRef ^mp; // указатель на структуру mp = gcnew MyPointRef; // выделение памяти для структуры // доступ к полям структуры mp->x = 25; mp->y = 30;
8. Каким образом описываются managed-массивы в среде CLR? Назначение ключевого слова array
В C++ native-массивы объявляются обычным для языка способом.
Более детально о массивах в C++ описывается в следующих статьях:
- Массивы. Часть 1. Определение массива. Одномерные массивы. Инициализация массива;
- Массивы. Часть 2. Двумерные массивы. Многомерные массивы.
Чтобы описать managed-массив используется ключевое слово array.
9. Пример объявления и использования массива managed-структур, которые объявлены с квалификатором ref, с помощью управляемого указателя (^)
Пусть в модуле «MyRefStruct.h» объявлена структура MyPointRef, которая описывает точку на координатной плоскости
ref struct MyPointRef { int x; int y; };
Работа с массивом из 10 managed-структур типа MyPointRef продемонстрирована ниже. Сначала нужно подключить файл структуры:
// подключить файл структуры #include "MyRefStruct.h"
Выделение памяти для массива и заполнения полей значениями структуры из другого программного кода (например, обработчика события клика на кнопке):
// массив m указателей на структуру, // описанную как managed с ключевым словом ref array <MyPointRef^> ^m; // выделение памяти для 10 указателей m = gcnew array <MyPointRef^>(10); // создание 10 объектов типа "структура MyPointRef" for (int i=0; i<10; i++) m[i] = gcnew MyPointRef; // выделение памяти для i-й структуры // заполнение полей x, y массива структур for (int i=0; i<10; i++) { m[i]->x = i*5; m[i]->y = i*i; }
Если объявить структуру MyPointRef с квалификатором value, то данный пример также будет работать.
10. Пример объявления и использования managed-массива на базовые типы (int, double) с помощью управляемого (^) указателя
В приведенном ниже примере объявляется массив из 20 целых чисел типа int. Для этого используется управляемый указатель (^).
Выделение памяти для массива происходит в 2 этапа:
- Выделение памяти для 20 указателей на тип int.
- Выделение памяти для каждого элемента типа int, на которые должны указывать указатели.
Для объявления массива используется ключевое слово array.
// managed-массив на базовые типы array <int ^> ^pi; // pi - указатель на массив типов int pi = gcnew array <int ^>(20); // выделение памяти для массива из 20 указателей // выделение памяти для каждого элемента массива for (int i=0; i<20; i++) pi[i] = gcnew int; // выделение памяти для i-го элемента массива // использование массива - заполнение значениями for (int i=0; i<20; i++) pi[i] = i*5; int d; d = (int)pi[2]; // d = 10
11. Пример объявления и использования массива указателей (^) на класс, которые объявленные как managed с использованием классификатора ref и ключевого слова array
В примере объявлен класс с именем MyClassRef, описывающий координаты точки на плоскости. Класс объявлен как managed (имеет квалификатор ref). Класс содержит:
- внутренние скрытые (private) члены данных x, y;
- конструктор класса MyClassRef();
- методы GetX() и GetY(), возвращающие значение членов данных x, y;
- метод SetXY(), устанавливающий новые значения членов данных x, y.
Класс описан в двух модулях (файлах):
- модуль «MyClassRef.h» – содержит объявление членов данных класса и его методов;
- модуль «MyClassRef.cpp» – содержит реализацию методов класса.
Текст модуля «MyClassRef.h»:
#pragma once // класс объявлен как managed ref class MyClassRef { // члены данных класса int x; // координата x int y; // координата y public: // методы класса MyClassRef(void); int GetX(void); int GetY(void); void SetXY(int nx, int ny); };
Текст модуля «MyClassRef.cpp»:
#include "StdAfx.h" #include "MyClassRef.h" // конструктор класса MyClassRef::MyClassRef(void) { x = y = 0; } // методы класса int MyClassRef::GetX(void) { return x; } int MyClassRef::GetY(void) { return y; } void MyClassRef::SetXY(int nx, int ny) { x = nx; y = ny; return; }
Чтобы из другого программного кода использовать методы класса надо предварительно подключить модуль «MyClassRef.h»:
#include "MyClassRef.h"
После этого можно использовать методы класса. Ниже продемонстрировано объявление и использование массива управляемых (managed) указателей (^) на класс из другого программного кода:
// массив mp managed-указателей на класс MyClassRef // сначала выделяется память для 10 указателей array <MyClassRef ^> ^mp = gcnew array <MyClassRef ^>(10); // выделение памяти для каждого класса, на который указывает указатель for (int i=0; i<10; i++) mp[i] = gcnew MyClassRef; // использование методов класса с помощью массива указателей mp[1]->SetXY(5, 6); mp[5]->SetXY(10, -200); int d; d = mp[1]->GetX(); // d = 5 d = mp[0]->GetY(); // d = 0 d = mp[5]->GetY(); // d = -200
Связанные темы
- Указатели. Часть 1. Общие понятия. Типы указателей. Управляемые и неуправляемые указатели. Указатели на функцию. Примеры использования
- Указатели. Часть 2. Неуправляемые указатели. Операции над указателями. Указатель на тип void. Выделение памяти. Нулевой указатель. Операция взятия адреса &
- Указатели. Часть 3. Неуправляемые указатели и массивы. Указатель на структуру. Указатель на класс
- Указатели. Часть 4. Указатели и строки символов. Использование указателей при преобразовании строк
- Указатели. Часть 5. Выделение памяти для указателя. Массивы указателей на базовые типы, функции, структуры, классы
- Массивы. Часть 1. Определение массива. Одномерные массивы. Инициализация массива
- Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
- Структуры. Часть 2. Выделение памяти для структуры. Вложенные структуры. Массивы native-структур
- Структуры. Часть 3. Работа с managed-структурами в среде CLR. Квалификаторы ref и value. Объявление структурных переменных. Массивы managed-структурных переменных. Инициализация managed-структур