pin_ptr (C++/CLI)
声明钉住 指针,仅使用公共语言运行时 (clr)。
所有运行时
(不适用于所有运行时间。) 此语言功能的备注
运行时的窗口
(此语言功能在运行时的窗口不支持。)
公共语言运行时
钉住 指针 是防止所指向的对象为转至垃圾回收堆的内部指针。 即公共语言运行时不更改钉住指针的值。 这是必需的,当您通过托管类的地址传递给非托管函数时,以便该地址不会在非托管解析时意外更改函数调用。
语法
[cli::]pin_ptr<cv_qualifier type> var = &initializer;
参数
cv_qualifier
const 或 volatile 限定符。 默认情况下,钉住指针是 volatile。 它是冗余,但不是错误声明钉住指针 volatile。type
initializer 的类型。var
pin_ptr 变量的名称。初始值设定项
可以分配给本机指针的引用类型、组件的托管数组,或其他对象的成员。
备注
pin_ptr 表示本机指针的函数的超集。 因此,可分配到本机指针的任何可能也被分配到 pin_ptr。 内部指针允许执行相同的设置操作与本机指针,包括比较和指针算法。
,在公共语言运行时将不会在垃圾回收期间情况下,会将托管类的对象或子对象可以锁定。 ,因为非托管物理函数调用的参数,此操作的基本用途是通过指向托管数据。 在回收循环中,运行时将检查已创建的元数据所指向的钉住指针,并且不会移动项。
锁定对象还锁定其值字段;即原始或值类型的字段。 但是,跟踪声明的字段句柄 (%) 没有锁。
锁定托管对象定义的子对象具有锁定整个对象的效果。
如果重新分配钉住指针指向一个新值,前一个指向不再被视为锁。
,仅当 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
示例
下面的示例演示,钉住指针可转换为另一种类型。
// 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