你如何处理C ++ / CLI中的句柄?

时间:2009-01-22 01:44:25

标签: c++-cli

我知道我也不是要问这个问题。请帮助我更好地形成我的问题。

我有点困难让我的思绪缠绕在手柄上 - 在某些方面,它看起来像指针。但与指针不同,似乎我可以直接将值赋给handle变量,它会影响底层数据值,而不是句柄本身。

测试代码清楚地表明,无论是否使用句柄,或者我“取消引用”句柄来获取数据,我都得到相同的值。显然,这不适用于非托管指针。我不理解的是什么?

#include <iostream>

int main()
{

  int ^y;
  int ^a, ^b, ^c;
  long x;

   y= gcnew int(100);
   a=y;
   b=y;
   c=y;

   c= gcnew int(200);
   b= 300;

   System::Console::WriteLine(y); // returns 100 (instead of something pointer-like)
   System::Console::WriteLine(*y); // also returns 100

   System::Console::WriteLine(a); // 100
   System::Console::WriteLine(b); // 300
   System::Console::WriteLine(c); // 200 

   x = static_cast<long>(y);
   *y = 10;

   System::Console::WriteLine(x); // 10
   System::Console::WriteLine(y); // 10
   System::Console::WriteLine(*y); // 10

  }

编辑添加 - 我怀疑WirteLine可能已经为我做了解除引用,但我原本预计静态强制转换不会。这与autounboxing有关吗?

4 个答案:

答案 0 :(得分:5)

C ++ / CLI允许这种语法有点令人遗憾。 int类型是值类型,hat用于引用类型。您的“y”变量不存储int,它存储System :: Object。分配时,编译器会自动生成装箱指令。 Console :: WriteLine()在显示一个盒装int的对象的值时没有问题。

经验法则:当它是一个类对象时使用hat,对于简单的值类型省略它。避免引用类型的堆栈语义(省略hat,以便在作用域结束时自动调用析构函数),直到你真正理解值和引用类型之间的差异以及Dispose()为何如此重要。

答案 1 :(得分:2)

使用WriteLine的副作用。

只是'y'被视为'对象引用'并且可能被查询为IFormattable,然后调用ToString()。 '* y'传递一个int。

要测试这个,请调用另一个函数Foo(int ^)并查看允许传入的内容,然后将其更改为“Foo(int)”。

我认为你只是被WriteLine的'varargs'性质所迷惑。​​

答案 2 :(得分:2)

不要依赖WriteLine告诉你* y和y是什么,从调试器运行它并自己检查* y和y以查看差异。

答案 3 :(得分:0)

将值类型的句柄看作是您自己编写的智能句柄,它具有运算符重载转换功能。这样,使用可以提供int的句柄(通过转换运算符)以及取消引用句柄来获取对象中包含的int。

关于Writeline,我认为它就像流输出操作符,其中隐式调用了许多转换。就像你可以安全地去cout&lt;&lt; y,你可以编写System :: Console :: WriteLine(y)。