Поделиться через


Уникальные указатели

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

int iAnInteger=50;

// The next statement makes ipAnIntegerPointer an
// alias for iAnInteger.
int *ipAnIntegerPointer = &iAnInteger;

// This statement creates an alias for ipAnIntegerPointer.
int *ipAnotherIntegerPointer = ipAnIntegerPointer;

В обычной программе C можно указать двоичное дерево с помощью следующего определения:

typedef struct _treetype 
{
    long               lValue;
    struct _treetype * left;
    struct _treetype * right;
} TREETYPE;

TREETYPE * troot;

Несколько указателей могут получить доступ к содержимому узла дерева. Как правило, это хорошо для нераспровержанных приложений. Однако этот стиль программирования создает более сложный код поддержки RPC. Заглушки клиента и сервера требуют дополнительного кода для управления данными и указателями. Базовый код заглушки должен разрешать различные указатели на адреса и определять, какая копия данных представляет самую последнюю версию.

Объем обработки может быть сокращен, если вы гарантируете, что указатель является единственным способом, которым приложение может получить доступ к этой области памяти. Указатель по-прежнему может иметь множество функций указателя C. Например, он может измениться между null и незначениями null или оставаться неизменными. В следующем примере показано это. Указатель null перед вызовом и указывает на допустимую строку после вызова:

указатель, изменяющийся между значениями NULL и не null

По умолчанию компилятор MIDL применяет атрибут указателя [ уникальный] ко всем указателям, которые не являются параметрами. Этот параметр по умолчанию можно изменить с помощью атрибута [ pointer_default] .

Уникальный указатель имеет следующие характеристики:

  • Он может иметь значение null.
  • Он может измениться с null наnull во время вызова. Если значение изменяется наnull, новая память выделяется при возврате.
  • Он может измениться сnull на null во время вызова. Когда значение изменяется на NULL, приложение отвечает за освобождение памяти.
  • Значение может измениться с одного значения, отличного отnull, на другое.
  • Хранилище, к которому указывает уникальный указатель, к которому не удается получить доступ с помощью любого другого указателя или имени в операции.
  • Возвращаемые данные записываются в существующее хранилище, если указатель не имеет значения null.

В следующем примере показано, как определить уникальный указатель.

/* IDL file */
[ 
  uuid(ba209999-0c6c-11d2-97cf-00c04f8eea45),
  version(1.0)
]
interface RefPtrInterface
{
  void RemoteFn([in, unique] char *ach);
}

В этом примере параметр ach является уникальным указателем на символьные данные, которые отправляются на сервер для обработки с помощью подпрограммы RemoteFn.