托管代码中的指针

本文介绍了C++/CLI中的托管代码指针Interior_ptr和Pin_ptr的使用方法及区别。Interior_ptr可以随垃圾回收移动,始终指向对象。Pin_ptr用于固定指针地址,防止垃圾回收期间地址变动,适用于外部调用。文章还对比了二者与普通指针的转换规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

托管代码中的指针

分类: C++/CLI   2790人阅读  评论(0)  收藏  举报
 
interior_ptr<type>
native pointer 的超集, native pointer 能做的, Interior pointer 也一样能做。当垃圾回收器移动对象时, Interior pointer 能随之移动,并始终指向该对象。
------ Pro Visual C++_CLI and the .NET 2.0 Platform p815
 
Interior _ptr 可以指向引用句柄、值类型、装箱类型句柄、托管类成员、托管数组的元素。 不能指向引用类型本身。
 
*ip  ip 所值的类型 type 的值
&ip  ip 指向托管堆中的地址
 
pin_ptr<type>
在外部调用托管堆中指针时,垃圾回收过程中该指针会发生改变,引起外部调用的错误。必须使用pin_ptr指针将该指针固定。
 
pinned pointer 可以指向引用句柄、值类型、托管数组的元素。 不能指向引用类型 ,但能指向引用类型的成员(不支持钉住由 new 表达式返回的整个对象。相反,需要钉住内部成员的地址。--MSDN)。可以完成native pointer的所有的功能,如指针比较和指针运算。
 
都不能由跟踪句柄直接赋值。而是必须由&操作符取地址。因为interior_ptr pin_ptr是独立的类,只能由地址赋值,而不能由托管类型赋值。
 
int ^ m_int = gcnew int(100);
interior_ptr <int> ipint = &*m_int; //ok
interior_ptr <int> ipint = m_int;   //error
Value  class  Vtest {}
Ref 
class  Rtest {}

Vtest 
^ vtest  =  gcnew Vtest;         // 值类型对象

pin_ptr
<  Vtest  >  pinp;
pinp 
=  vtest;             // error
pinp  =   &*  vtest;         // ok
interior_ptr <  Vtest  >  ip;
ip 
=   &*  vtest;         // ok


pin_ptr
<  Vtest  ^>  pinhundle;
pinhundle 
=  vtest;         // error
pinhundle  =   &  vtest;         // ok
interior_ptr <  Vtest  ^>  iphundle;
iphundle 
=   &  vtest;         // ok


RTest 
^ rtest  =  gcnew RTest;         // 引用类型对象
pin_ptr <  Rtest  >  pinp;              // error , 不可以钉住引用类型对象
interior_ptr  <  Rtest  >  pinp;     // error , 不可以指向引用类型对象


ref   class  G  {
public:
   
void incr(int* pi) *pi += 1; }
}
;
ref   struct  H  int j; } ;
void  f( G ^  g )  {
   H 
^ph = gcnew H;
   Console::WriteLine(ph
->j);
   pin_ptr
<int> pj = &ph->j;    //ok,可以钉住引用类型对象的成员
   g->incr(  pj );
   Console::WriteLine(ph
->j);
}

  

 

Pin_ptr指针使用例子
value  class  Test 
{
public:
    
int i; 
}
;

#pragma  unmanaged
void  incr ( int   * i)
{
    (
*i) += 10;
}


#pragma  managed
void  main () 
{
    Test 
^test = gcnew Test();
    interior_ptr
<int> ip = &test->i;
    (
*ip) = 5;
//  incr( ip );            // invalid 
    pin_ptr<int> i = ip;   // i is a pinned int pointer
    incr( i );             // pinned pointer to interior pointer passed to a
                           
// native function call expecting a native pointer
    Console::WriteLine ( test->i );
}

 
非托管代码中的函数void incr(int *i)需要int指针,不能将interior_ptr<int>的ip传递给该函数。因为内部指针会随着垃圾回收改变地址,而将其转换为pin_ptr<int>,就是将地址固定,以供外部函数incr(int* i)调用该指针。
 
和*指针的转换
正因为 pin_ptr <> 所指向的地址是固定的,因此才能和*指针转换。而interior_ptr<>无此性质。
    pin_ptr < ClassValue >  pValue  =   & value;;
    ClassValue
*  p  =  pValue;             // ok
 
interior_ptr 就不可以和*指针转换。
    interior_ptr < ClassValue >  pValue  =   & value;;
    ClassValue
*  p  =  pValue;             // error

 

 

值类型的指针
在新语法中,值类型指针分为两种类型: V* (限于非 CLR 堆位置)和内部指针  interior_ptr<V> (允许但不要求托管堆内的地址)。
// may not address within managed heap
V *pv = 0;
 
// may or may not address within managed heap
interior_ptr<V> pvgc = nullptr;
托管扩展中的下列声明全部映射到新语法中的内部指针。(它们是  System 命名空间内的值类型。)
Int32 *pi;   // => interior_ptr<Int32> pi;
Boolean *pb; // => interior_ptr<Boolean> pb;
E *pe;       // => interior_ptr<E> pe; // Enumeration
内置类型不被认为是托管类型,尽管它们确实在 System 命名空间内作为类型的别名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值