Что такое дескриптор в C ++?

98

Мне сказали, что дескриптор является своего рода указателем, но не указателем, и что он позволяет вам сохранять ссылку на объект, а не на сам объект. Какое более подробное объяснение?

Ксенопримат
источник
2
Заглянув в шаблон «Цепочка ответственности», вы узнаете, что «Дескриптор» - это в основном узел, а «Обработчик» - их небольшой набор. «Магия» исходит от рекурсии

Ответы:

100

Дескриптором может быть что угодно, от целочисленного индекса до указателя на ресурс в пространстве ядра. Идея состоит в том, что они предоставляют абстракцию ресурса, поэтому вам не нужно много знать о самом ресурсе, чтобы использовать его.

Например, HWND в Win32 API - это дескриптор окна. Сам по себе он бесполезен: вы не можете почерпнуть из него никакой информации. Но передайте его нужным функциям API, и вы сможете выполнять с ним множество различных трюков. Внутренне вы можете рассматривать HWND как просто индекс в таблице окон графического интерфейса пользователя (что может не обязательно совпадать с тем, как он реализован, но в этом есть смысл).

РЕДАКТИРОВАТЬ: Не уверен на 100%, что конкретно вы задавали в своем вопросе. В основном речь идет о чистом C / C ++.

Мэтью Иселин
источник
14
Ручка может быть полезна для сохранения состояний (среди прочего). Если у вас есть данные в такой структуре, как std :: vector. Ваш объект может находиться в разных местах памяти в разное время во время выполнения программы, что означает, что ваш указатель на эту память изменит значения. С дескриптором он никогда не меняется, он всегда ссылается на ваш объект. Представьте себе сохранение состояния программы (как в игре) - вы не сохраните местоположение указателя на данные, а затем снова импортируете данные и попытаетесь получить этот адрес в памяти. Однако вы можете сохранить дескриптор со своими данными и импортировать данные и дескриптор.
SinisterRainbow
Можно ли преобразовать HANDLE в аналог в Linux? Мне нужно перенести программу, которая использует HANDLE, с Windows на Linux.
Корнел Верстер
1
Это правильный ответ, что они могут быть любыми и что код, который их использует, определяет тип дескриптора. Я попытался сделать более сжатую версию своего подобного ответа, ничего не мог с собой поделать, для потомков. @CornelVerster - в Linux они такие же. Я имею в виду не ручки ОС, а концепт. Таким образом, это зависит от дескриптора в отношении его миграции или даже необходимости миграции.
дяста
@Matthew Iselin: в какой-либо документации API они определяют, что вещь является обработчиком, тогда мы должны знать, чтобы передать их функциям, иначе как мы можем узнать, что такое обработчик в документации API
Амин Хормей,
51

Дескриптор - это указатель или индекс без прикрепленного к нему видимого типа. Обычно вы видите что-то вроде:

 typedef void* HANDLE;
 HANDLE myHandleToSomething = CreateSomething();

Поэтому в вашем коде вы просто передаете HANDLE как непрозрачное значение.

В коде, который использует объект, он приводит указатель к реальному типу структуры и использует его:

 int doSomething(HANDLE s, int a, int b) {
     Something* something = reinterpret_cast<Something*>(s);
     return something->doit(a, b);
 }

Или он использует его как индекс для массива / вектора:

 int doSomething(HANDLE s, int a, int b) {
     int index = (int)s;
     try {
         Something& something = vecSomething[index];
         return something.doit(a, b);
     } catch (boundscheck& e) {
         throw SomethingException(INVALID_HANDLE);
     }
 }
Jmucchiello
источник
29

Дескриптор - это своего рода указатель, обычно это способ ссылки на какой-либо объект.

Было бы точнее сказать, что указатель - это один из типов дескрипторов, но не все дескрипторы являются указателями.

Например, дескриптор также может быть некоторым индексом в таблице в памяти, которая соответствует записи, которая сама содержит указатель на некоторый объект.

Ключевым моментом является то, что когда у вас есть «дескриптор», вы не знаете и не заботитесь о том, как этот дескриптор на самом деле в конечном итоге идентифицирует то, что он идентифицирует, все, что вам нужно знать, это то, что он делает.

Также должно быть очевидно, что не существует однозначного ответа на вопрос «что такое дескриптор», потому что дескрипторы для разных вещей, даже в одной и той же системе, могут быть реализованы разными способами «под капотом». Но вам не стоит беспокоиться об этих различиях.

Дельтика
источник
6

В C ++ / CLI дескриптор - это указатель на объект, расположенный в куче сборщика мусора. Создание объекта в (неуправляемой) куче C ++ достигается с помощью, newа результатом newвыражения является «нормальный» указатель. Управляемый объект размещается в куче GC (управляемой) с gcnewвыражением. В результате получится ручка. Вы не можете выполнять арифметические операции с указателями для дескрипторов. У вас нет свободных ручек. GC позаботится о них. Кроме того, сборщик мусора может перемещать объекты в управляемой куче и обновлять дескрипторы, чтобы они указывали на новые местоположения во время работы программы.

Мехрдад Афшари
источник
5

Это появляется в контексте идиомы Handle-Body-Idiom , также называемой идиомой Pimpl. Это позволяет сохранить ABI (двоичный интерфейс) библиотеки одним и тем же, сохраняя фактические данные в другом объекте класса, на который просто ссылается указатель, содержащийся в объекте «дескриптор», состоящем из функций, которые делегируют этому классу » Тело ».

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

Йоханнес Шауб - litb
источник
2

Ручка - это то, что вы хотите.

Дескриптор может быть целым числом без знака, используемым в некоторой таблице поиска.

Дескриптор может быть указателем на более крупный набор данных или на него.

Это зависит от того, как ведет себя код, использующий дескриптор. Это определяет тип ручки.

Причина, по которой используется термин « ручка », - вот что важно. Это указывает на них как на тип идентификации или доступа к объекту. Это означает, что для программиста они представляют собой «ключ» или доступ к чему-либо.

дьяста
источник
2

HANDLE hnd; такой же как void * ptr;

HANDLE - это typedef, определенный в файле winnt.h в Visual Studio (Windows):

typedef void *HANDLE;

Узнать больше о РУЧКА

Куламани
источник
1
Это применимо только к Windows и только к одному из многих типов дескрипторов, используемых в архитектуре Windows. Однако это то, что было бы известно как «обычный дескриптор уровня приложения Windows».
дяста