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


pin_ptr (C++/CLI)

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

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

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

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

(Эта функция языка не поддерживается в среде выполнения Windows).

Среда CLR

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

Синтаксис

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

Параметры

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

  • type
    Тип initializer.

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

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

Примечания

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

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

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

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

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

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

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

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

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

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

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

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

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

  • член класса

  • конечный тип приведения типов.

pin_ptr находится в пространстве имен cli. Для получения дополнительной информации см. Пространства имен platform, default и cli (расширения компонентов C++).

Дополнительные сведения о внутренних указателях см. в разделе 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());
}

Output

  

Пример

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

// 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);
};

Output

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);
}

Output

8