pin_ptr (C++/CLI)

Объявляет закрепляющий указатель, который используется только со средой CLR.

Все среды выполнения

(Отсутствуют комментарии для этой возможности языка, которая применяется во всех средах выполнения.)

Среда выполнения Windows

(В среде выполнения Windows эта возможность языка не поддерживается.)

Среда CLR

Закрепляющий указатель — это внутренний указатель, запрещающий объекту, на который он указывает, перемещаться в кучу со сборкой мусора. То есть значение закрепляющего указателя не изменяется средой CLR. Это необходимо при передаче адреса управляемого класса в неуправляемую функцию, чтобы исключить неожиданное изменение адреса во время разрешения вызова неуправляемой функции.

Синтаксис

[cli::]pin_ptr<cv_qualifiertype>var = &initializer;

Параметры

cv_qualifier
const или volatile квалификаторы. По умолчанию указан указатель volatileна закрепление. Он является избыточным, но не ошибкой для объявления указателя volatileна закрепление.

type
Тип инициализатора.

var
Имя переменной pin_ptr.

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

Замечания

pin_ptr представляет собой надмножество функциональности собственного указателя. Таким образом, все, что можно присвоить собственному указателю, можно также присвоить указателю pin_ptr. Внутреннему указателю разрешается выполнять тот же набор операций, что и собственному указателю, включая сравнение и вычисления с указателями.

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

При закреплении объекта также закрепляются его поля значений, то есть поля простых типов или типов значений. Однако поля, объявленные c помощью дескриптора отслеживания (%), не закрепляются.

Закрепление части объекта, определенной в управляемом объекте, имеет эффект закрепления всего объекта.

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

Объект закреплен, только пока pin_ptr указывает на него. Если закрепляющий указатель объекта вышел за пределы области видимости или имеет значение nullptr, объект больше не закреплен. После выхода pin_ptr за пределы области видимости объект, который был закреплен, может быть перемещен в кучу сборщиком мусора. Все собственные указатели, по-прежнему указывающие на объект, не обновляются и разыменование одного из них может вызвать неустранимое исключение.

При отсутствии закрепляющих указателей, указывающих на объект, (все закрепляющие указатели вышли за пределы области видимости, были переназначены для указания на другие объекты или им присвоено значение nullptr) объект гарантированно не будет закреплен.

Закрепляющий указатель может указывать на дескриптор ссылки, тип значения, дескриптор упакованного типа, член управляемого типа или элемент управляемого массива. Он не может указывать на ссылочный тип.

Получение адреса pin_ptr, указывающего на собственный объект, приводит к неопределенному поведению.

Закрепляющие указатели можно объявлять только как нестатические локальные переменные в стеке.

Закрепляющие указатели нельзя использовать в качестве:

  • параметры функции

  • возвращаемого типа функции;

  • члена класса;

  • целевого типа приведения типов.

pin_ptr находится в пространстве имен cli. Дополнительные сведения см. в статье Platform, default, and cli Namespaces (C++/CLI and C++/CX) (Пространства имен Platform, default и cli (C++/CLI и C++/CX)).

Дополнительные сведения о внутренних указателях см. в разделе interior_ptr (C++/CLI).

Дополнительные сведения о закреплении указателей см. в разделе "Практическое руководство. Закрепление указателей и массивов " и "Практическое руководство. Объявление указателей на закрепление и типы значений".

Требования

Параметр компилятора: /clr

Примеры

В следующем примере pin_ptr используется для ограничения позиции первого элемента массива.

// pin_ptr_1.cpp
// compile with: /clr
using namespace System;
#define SIZE 10

#pragma unmanaged
// native function that initializes an array
void native_function(int* p) {
   for(int i = 0 ; i < 10 ; i++)
    p[i] = i;
}
#pragma managed

public ref class A {
private:
   array<int>^ arr;   // CLR integer array

public:
   A() {
      arr = gcnew array<int>(SIZE);
   }

   void load() {
   pin_ptr<int> p = &arr[0];   // pin pointer to first element in arr
   int* np = p;   // pointer to the first element in arr
   native_function(np);   // pass pointer to native function
   }

   int sum() {
      int total = 0;
      for (int i = 0 ; i < SIZE ; i++)
         total += arr[i];
      return total;
   }
};

int main() {
   A^ a = gcnew A;
   a->load();   // initialize managed array using the native function
   Console::WriteLine(a->sum());
}
45

В следующем примере показано, что внутренний указатель можно преобразовать в закрепляющий, и что возвращаемый тип оператора взятия адреса (&) является внутренним указателем, если операнд находится в управляемой куче.

// pin_ptr_2.cpp
// compile with: /clr
using namespace System;

ref struct G {
   G() : i(1) {}
   int i;
};

ref struct H {
   H() : j(2) {}
   int j;
};

int main() {
   G ^ g = gcnew G;   // g is a whole reference object pointer
   H ^ h = gcnew H;

   interior_ptr<int> l = &(g->i);   // l is interior pointer

   pin_ptr<int> k = &(h->j);   // k is a pinning interior pointer

   k = l;   // ok
   Console::WriteLine(*k);
};
1

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

// pin_ptr_3.cpp
// compile with: /clr
using namespace System;

ref class ManagedType {
public:
   int i;
};

int main() {
   ManagedType ^mt = gcnew ManagedType;
   pin_ptr<int> pt = &mt->i;
   *pt = 8;
   Console::WriteLine(mt->i);

   char *pc = ( char* ) pt;
   *pc = 255;
   Console::WriteLine(mt->i);
}
8
255