CLR语法中,值类型指针分为两种类型:V*(限于非 CLR 堆位置)和内部指针 interior_ptr<V>(允许但不要求托管堆内的地址)。
钉住指针
通常,在压缩阶段,垃圾回收器可选择将驻留在 CLR 堆上的对象移动到堆内的不同位置。这种移动对于跟踪句柄、跟踪引用和内部指针而言不是问题,它们都透明地更新这些实体。但是,如果用户在运行时环境外传递了 CLR 堆上对象的地址,这种移动就会导致问题。在这种情况下,对象的不稳定运动可能导致运行时失败。要避免此类对象的移动,必须在本地将它们钉在自己的位置上以供外部使用。
在托管扩展中,“钉住指针”是通过使用 __pin 关键字限定指针声明来声明的。下面是一个来自托管扩展规范的经过略微修改的示例:
复制代码
__gc struct H { int j; };
int main()
{
H * h = new H;
int __pin * k = & h -> j;
// …
};
在新的语言设计中,钉住指针是使用类似于内部指针的语法来声明的。
复制代码
ref struct H
{
public:
int j;
};
int main()
{
H^ h = gcnew H;
pin_ptr<int> k = &h->j;
// …
}
interior_ptr
Declares a pointer to inside a reference type, but not to the object itself. An interior pointer can point to a reference handle, value type, boxed type handle, member of a managed type, or to an element of a managed array.
cli::interior_ptr<cv_qualifier type> var = &initializer;
Remarks
A native pointer is not able to track an item as its location changes on the managed heap, which results from the garbage collector moving instances of an object. In order for a pointer to correctly refer to the instance, the runtime needs to update the pointer to the newly positioned object.
An interior_ptr represents a superset of the functionality of a native pointer. Therefore, anything that can be assigned to a native pointer can also be assigned to an interior_ptr. An interior pointer is permitted to perform the same set of operations as native pointers, including comparison and pointer arithmetic.
An interior pointer can only be declared on the stack. An interior pointer cannot be declared as a member of a class.
Since interior pointers exist only on the stack, taking the address of an interior pointer yields an unmanaged pointer.
interior_ptr has an implicit conversion to bool, which allows for its use in conditional statements.
For information on how to declare an interior pointer that points into an object that cannot be moved on the garbage-collected heap, see pin_ptr.
interior_ptr is in the cli namespace. See cli Namespace for more information.
//Example
// interior_ptr.cpp
// compile with: /clr
using namespace System;
ref class MyClass {
public:
int data;
};
int main() {
MyClass ^ h_MyClass = gcnew MyClass;
h_MyClass->data = 1;
Console::WriteLine(h_MyClass->data);
interior_ptr<int> p = &(h_MyClass->data);
*p = 2;
Console::WriteLine(h_MyClass->data);
// alternatively
interior_ptr<MyClass ^> p2 = &h_MyClass;
(*p2)->data = 3;
Console::WriteLine((*p2)->data);
}