на начало
На главную страницу
Форум   

Статья :: Управляемые и неуправляемые ссылки и типы значений


Управляемые и неуправляемые ссылки и типы значений

Существуют фундаментальные отличия между тем, как управляемые и неуправляемые коды обрабатывают ссылки и типы значений. Неуправляемый код C++ позволяет объявлять локальные переменные, параметры методов и члены классов как относящиеся к типам, определенным неуправляемыми классами или структурами. Такие типы называются типами значений, так как подобные переменные содержат значения, которые в действительности являются данными. C++ также позволяет определять переменную как указатель или как ссылку на тип, определенный классом или структурой. Такие типы называются ссылочными типами, или типами ссылки, так как переменные реально не содержат значения, которые являются объектом, а вместо этого являются ссылками на объект соответствующего типа в неуправляемой динамически распределяемой области памяти. Это может немного удивить, потому что C++ пытается провести концептуальное разграничение между типами указателей и ссылочными типами. И все же в действительности ссылка в C++ является просто разновидностью постоянного (константного) указателя.
Объявление типа значения представляет собой в действительности выделение пространства памяти под реальные значения. Однако в управляемом коде нельзя объявить управляемый класс или структуру в качестве типа значения (если только не используется ключевое слово _value (значение)). Это можно увидеть в следующем примере программы, ManagedAndUnmanagedRefAndValTypes, где компилятор отметит как ошибочное объявление переменной в качестве типа значения с помощью управляемого класса ManagedClass. Для того чтобы это увидеть, попробуйте раскомментировать строку программы, содержащую оператор ManagedClass mcObj;. В результате появится сообщение об ошибке, извещающее, что вы, возможно, хотели объявить указатель, а не значение.
С другой стороны, не будет ошибкой определение переменной типа значения с помощью неуправляемого класса UnmanagedClass. Заметим, что также не будет ошибкой создание экземпляров класса ManagedClass в управляемой динамически распределяемой области памяти и экземпляров класса UnmanagedClass в неуправляемой динамически распределяемой области памяти с использованием оператора new (создать). Единственным отличием в этих случаях будет то, что для управляемого объекта не нужен оператор delete (удалить) для того, чтобы избежать утечки памяти, а для неуправляемого экземпляра такой оператор понадобится.
В нашем конкретном примере оператор delete (удалить) используется в последней строке для удаления объекта pmcobj, и комментарий утверждает, что "удалять обычно не требуется, но здесь необходимо". Оператор delete (удалить) добавлен в последнюю строку программы не потому, что непосредственная очистка требуется для управляемого объекта (сборщик мусора это сделает и без нас), а добавлен он из временных соображений. Это сделано потому, что вызов Console:: WriteLine в деструкторе управляемого класса в противном случае производился бы в самом конце выполнения программы, уже после того, как выходной поток Console (Консоль) был бы закрыт. Другими словами, если бы деструктор не был вызван явно оператором delete (удалить), управляемый объект попытался бы выполнить вывод в несуществующий поток, что вызвало бы исключение (System.ObjectDisposedException: Cannot access a closed Stream — Нельзя обращаться к закрытому потоку). Это демонстрирует наиболее общую причину явного удаления управляемого объекта, которая заключается в том, что иногда требуется явно указать момент разрушения объекта.
Хотелось бы еще обратить внимание на то, что компилятор обрабатывает примитивные типы данных (такие как int, float (с плавающей точкой), double (с удвоенной точностью), char (символ), и т.д.) не так, как управляемые классы сборщика мусора (_дс) или структуры сборщика мусора (_дс), потому что примитивные типы всегда являются типами значений.

//ManagedAndUnmanagedRefAndValTypes.срр
fusing <mscorlib.dll>
using namespace System;
// использование пространства имен Система;
_gc class ManagedClass
// класс сборщика мусора ManagedClass
{
public:
ManagedClass()
{
Console::WriteLine("ManagedClass");
}
^ManagedClass()
{
Console::WriteLine("~ManagedClass");
}
};
_nogc class UnmanagedClass
{
public:
UnmanagedClass()
{
Console::WriteLine("UnmanagedClass"); }
-UnmanagedClass() (
Console::WriteLine("-UnmanagedClass"); } };
void main(void) {
ManagedClass *pmcObj = new ManagedClass();
//ManagedClass mcObj; // ошибка, тип значения, не допустим
UnmanagedClass *pumcObj = new UnmanagedClass() ;
delete pumcObj;
// требуется удалить из-за отсутствия сборки мусора
UnmanagedClass umcObj; // нет ошибки, тип значения допустим
int i = 3;
// нет ошибки, тип значения допустим для примитивных типов 'delete pmcObj;
// удалять обычно не требуется, но здесь необходимо
}

Вот что выведет приведенный пример программы:

ManagedClass UnmanagedClass
-UnmanagedClass UnmanagedClass
-ManagedClass
-UnmanagedClass


Управляемые и неуправляемые ссылки и типы значений

страницы в данном разделе 
Глава 15. Смешивание управляемого и неуправляемого кода Смешивание управляемого и неуправляемого кода
Сравнение управляемого и неуправляемого кода Причины смешивания управляемого и неуправляемого кодов
Неуправляемый или опасный? Управляемые и неуправляемые ссылки и типы значений
Ограничения на использование управляемых типов в C++ Вызов управляемого кода из неуправляемого и обратный вызов
Сравнение программирования на C++ с использованием модели компонентных объектов Microsoft (COM) и .NET Доступ из управляемого кода к компонентам, построенным на основе модели компонентных объектов Microsoft (COM)
Сервисная программа Tibinp. ехе Унаследованный компонент на основе модели компонентных объектов Microsoft (COM)
Действующий клиент на основе модели компонентных объектов Microsoft (COM) Создание клиента на основе модели компонентных объектов Microsoft (COM) с помощью управляемого C++
Разработка управляемого клиента на основе модели компонентных объектов Microsoft (COM) с помощью С# Создание с помощью управляемого C++ клиента на основе модели компонентных объектов Microsoft (COM) без метаданных
Создание с помощью С# управляемого клиента на основе модели компонентных объектов Microsoft (COM) без метаданных Доступ к управляемым компонентам из клиентов на основе модели компонентных объектов Microsoft (COM)
Раннее связывание клиента на основе модели компонентных объектов Microsoft (COM) с компонентами .NET Динамическое связывание клиента на основе модели компонентных объектов Microsoft (COM) с компонентами .NET
Явное определение интерфейса Службы обращения к платформе: Plnvoke (Platform Invocation Services)
Резюме >  


Содержание сайта (выборка)
Apache
Протоколы TCP/IP (принципы, протоколы и архитектура)



PHP, PELR, JSP
PHP
JavaServer Pages (JSP)

Базы данных
Основы mysql
СУБД INFORMIX
СУБД POSTGRES
Основы проектирования реляционных баз данных

HTML, javascript
Спецификация HTML 4.01
Каскадные Таблицы Стилей, Уровень 2
Клиентский JavaScript. Справочник.
JavaScript руководство пользователя
Серверный JavaScript 1.4. Руководство по Использованию.

Паскаль, C, C++, C#
GCC (примеры)
FAQ Валентинa Озеровa DELPHI
C



 
© faq.pp.ru, справочник программиста