Bootstrap

pin_ptr (C++/CLI)


Visual Studio 2015
 

若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档

声明 钉住指针,仅使用在公共语言运行时。

(无适用于所有运行时的语言功能的备注。)

(此功能在 Windows 语言运行时不受支持。)

一个 钉住指针 是防止您的对象移动将在垃圾回收堆的内部指针。 也就是说钉住指针的值不是由公共语言运行时更改。 当向非托管函数传递托管类的地址时,这很有用,因为在解析非托管函数调用的过程中,该地址不会意外更改。

语法

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

参数

cv_qualifier
const 或 volatile 限定符。 默认情况下,钉住指针是 volatile。 为冗余,而不是错误声明钉住指针 volatile

type
initializer 的类型。

var
pin_ptr 变量的名称。

initializer
引用类型元素,托管数组,或者任何其他的成员可以分配给本机指针的对象。

备注

pin_ptr 表示本机指针的功能扩展。 因此,可以分配给本机指针的任何也可以分配给 pin_ptr。 内部指针允许运行同一组操作与本机指针,其中包括比较和指针算法。

托管类的对象或子对象可以固定,在垃圾回收过程情况下公共语言运行时不会移动。 使用此的基本用法是传递指向托管数据为托管函数调用的一个实参。 在回收周期期间,运行时将检查创建的元数据。因此不移动指向的钉住指针的项。

固定对象还固定字段;其值即或基元值类型字段。 但是,声明的字段跟踪句柄 (%) 不使用锁定。

固定在宿主的对象定义的子对象的固定整个对象的效果。

如果固定指针重新分配到新值,以前的实例指向不再将该表视为锁定。

对象固定,仅当它的 pin_ptr 指向它。 对象不再被锁定,则其固定指针超出范围,或者设置为 nullptr。 在 pin_ptr 超出范围之后,固定对象在堆可以移动被垃圾回收器回收。 仍然指向对象的任何本机指针不会更新,并间接引用其中一个可能引发一不可恢复的异常。

如果对对象的固定指针 (指向所有钉住指针超出了范围,重新分配到其他对象的点或分配 nullptr),不保证对象不锁定。

钉住指针可以指向句柄引用、值类型或装箱类型的托管类型的句柄、成员或托管数组的元素。 它不能指向引用类型。

将指向本机 pin_ptr 对象的地址导致未定义的行为。

钉住指针只能声明作为堆栈上的非静态局部变量。

无法使用钉住指针所示:

  • 函数参数

  • 作为函数的返回类型。

  • 类成员的声明

  • 目标的类型约束。

pin_ptr 是cli命名空间中的类型。 有关详细信息,请参阅Platform、default 和 cli 命名空间

有关智能指针的更多信息,请参见 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

45 示例

下面的示例表示内部指针转换为钉住的指针,并且,类型为返回 address-of 运算符 (&) 是内部指针,当操作数在托管堆时。

// 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
255

;