__pin

Примечание   Этот раздел относится только к версии 1 статьи "Управляемые расширения для C++". Приведенный здесь синтаксис должен использоваться только для обслуживания кода версия 1. Сведения об использовании аналогичных функциональных возможностей в новом синтаксисе см. в разделе pin_ptr.

Блокирует перемещение объекта или внедренного объекта управляемого класса средой CLR во время сборки мусора.

__pin identifier

Заметки

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

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

В MSIL отсутствует понятие "область видимости блока" — все локальные переменные находятся в области видимости функции. Чтобы сообщить системе о том, что закрепление больше не действует, компилятор создает код, который присваивает значение NULL закрепляющему указателю. Это также можно сделать самостоятельно, если требуется отменить закрепление объекта, не выходя из блока.

Не следует преобразовывать закрепляющий указатель в неуправляемый указатель и продолжать использовать этот неуправляемый указатель после отмены закрепления объекта (после выхода закрепляющего указателя за пределы области). В отличие от gc-указателей закрепляющие указатели можно преобразовать в неуправляемые nogc-указатели. Однако ответственность за сохранение закрепления при использовании неуправляемого указателя лежит на пользователе.

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

// keyword_pin_scope_bad.cpp
// compile with: /clr:oldSyntax /LD
#using <mscorlib.dll>
__gc struct X {
   int x;
};
 
int* Get_x( X* pX ) {
   int __pin* px = &pX -> x;
   return px;   // BE CAREFUL px goes of scope, 
                // so object pointed by it is no longer pinned,
                // making the return value unsafe.
}

Ниже приведен пример правильного поведения.

// keyword_pin_scope_good.cpp
// compile with: /clr:oldSyntax /LD
#using <mscorlib.dll>
__gc struct X {
   int x;
};
 
int Get_x( X* pX ) {
   int __pin* px = &pX -> x;
   return *px;   // OK, value obtained from px before px out of scope
}

Пример

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

// keyword__pin.cpp
// compile with: /clr:oldSyntax
#using <mscorlib.dll>
#include <iostream>

__gc class G { 
public: 
   int i; 
   G() {i = 0;};
};

class H {
public:
   // unmanaged function
   void incr(int * i) {
      (*i)++; 
      std::cout << *i << std::endl;
   };
};

int main() {
   G __pin * pG = new G;  // pG is a pinning pointer
   H * h = new H;
   // pointer to managed data passed as actual parameter of unmanaged 
   // function call
   h->incr(& pG -> i); 
}

Вывод

1