На этом шаге мы рассмотрим типы указателей.
На предыдущем шаге мы разобрали понятие указателя в общем смысле. Однако в VC++ это понятие несколько расширено, что вполне естественно для развивающихся систем. Здесь рассматриваются указатели трех типов:
Чтобы понять суть сказанного, вспомним, что ранее упоминалась среда CLR - это менеджер, который управляет исполнением кода, памятью, потоками и работой с удаленными компьютерами, при этом строго обеспечивая безопасность и создавая надежность исполнения кода.
CLR является добавкой-расширением C++, введенной фирмой Microsoft, начиная с версии VC++ 2005. Подключение к вашему проекту этого менеджера осуществляется на этапе компиляции. Если вы посмотрите свойства вашего проекта с помощью опции Project | Properties (Проект | Свойства) и в открывшемся диалоговом окне выберете папку Configuration Properties/General (Свойства конфигурации/Общие), то в правой части окна увидите настраиваемое свойство Common Language Runtime support (Поддержка общеязыковой среды выполнения), которое имеет значение "Поддержка CLR-среды" (рисунок 1).
Рис.1. Подключение к проекту CLR
Среда версии 2010 в режиме CLR понимает программы, использующие "родные" указатели, обозначаемые символом * (это видно из примера приведенной ниже программы), хотя эта же среда предусматривает совсем иное обозначение указателя, что мы увидим несколько позже.
Без режима CLR, когда вы в своей программе работаете с некоторыми объектами (здесь нам приходится забегать вперед, ибо объекты - это предмет более позднего изучения, когда мы станем знакомиться с классами), вы должны сами заботиться об их размещении в памяти, выделяемой средой. Память для вашего приложения выделяется в так называемой "куче": в ней вы размещаете свои объекты, там же сами должны освобождать память, когда перестаете работать с объектом, иначе куча может переполниться и процесс выполнения приложения прервется. Это так называемая неуправляемая куча. Указатели на участки памяти в такой куче обозначаются символом * (т. е. ранее мы раcсматривали указатели для неуправляемой памяти). Вот два последних типа указателя и являются традиционными указателями C/C++ на объекты в нерегулируемом объеме памяти, выделяемой для исполнения приложения.
Другое дело, когда включается режим CLR. Такое приложение отличается от обычного тем, что его заготовка обеспечивает подключение к приложению специального системного пространства System, содержащего объекты, размещение в памяти которых надо автоматически регулировать. Так вот: режим CLR работает уже с управляемой кучей памяти, в которой размещение объектов и ее освобождение от них происходит под управлением среды. Такой сервис входит в язык Java, где не надо делить кучу на управляемую и неуправляемую.
Регулируемый указатель - это тип указателя, который ссылается на объекты (адреса памяти, по которым можно обращаться к объектам), расположенные в общей регулируемой куче памяти, предоставленной приложению в момент его исполнения. Для таких указателей принято специальное обозначение: вместо символа * применяется символ ^.
Создание CLR привело к необходимости разработки аппарата преобразования переменных, относящихся к одной куче, в адреса другой кучи (переход от управляемой кучи к неуправляемой и наоборот). Этот процесс назвали маршаллизацией. Существует специальная библиотека, обеспечивающая этот процесс.
При рассмотрении работы с компонентами так называемых форм вы увидите, что регулируемые указатели создаются в обработчиках событий компонентов и что свойства проектов, работающих с объектами, содержат автоматическое подключение при компиляции поддержки режима CLR. В среде VC++ существует специальная утилита gcnew, которая формирует экземпляр какого-то объекта, выделяя ему (экземпляру) некоторую память, и возвращает ссылку на этот экземпляр.
Ниже приводится пример программы, результат работы которой представлен на рисунке 2. Этот пример надо рассматривать просто как демонстрацию работы с объектом "Структура", суть которой мы рассмотрим в следующих шагах.
// PtrStruc.cpp: главный файл проекта. #include "stdafx.h" using namespace System; ref struct Message { System::String ^sender, ^receiver, ^data; }; int main() { Message^ M = gcnew Message; M->sender="Сообщение для всех"; M->data="20.01.2019"; Console::WriteLine(M->sender); Console::WriteLine(M->data); Console::WriteLine(L"Здравствуй, мир!"); Console::ReadLine(); //для задержки экрана return 0; }
Здесь объявлена некая структура Message ссылочного (ref) типа. Элементами ее являются указатели ^sender, ^receiver, ^data на объект типа String (строковые данные). В основной функции main() для структуры Message утилитой gcnew выделяется память и возвращается указатель M типа Message на эту структуру.
Рис.2. Результат работы приложения
Шаблон CLR, когда мы хотим использовать регулируемые указатели, предполагает подключение к тексту программы специального пространства System, содержащего классы, которые задают ссылочные типы данных и функции работы с ними. В частности функция WriteLine() (вывод на печать) принадлежит этому же пространству. А нам как раз и надо работать с такими данными.
На следующем шаге мы рассмотрим указатели и массивы.