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

时间:2022-09-02 08:54:54

I know I'm not asking this quite right, either. Please help me better form my question.

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

I'm having a bit of a hard time getting my mind wrapped around handles -- in some ways, it looks like pointers. But unlike pointers, it seems like I can assign values directly to the handle variable, and it affects the underlying data value, not the handle itself.

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

The test code clearly shows that I get the same value whether I use the handle, or if I "dereference" the handle to get to the data. Clearly, this wouldn't work with unmanaged pointers. What am I not understanding?

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

#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

  }

Edit to add -- I suspected that WirteLine might have done the dereferencing for me, but I would have expected the static cast to long would not. Is this related to autounboxing as welll?

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

4 个解决方案

#1


It's a bit sad that C++/CLI allows this syntax. The int type is a value type, the hat is used for reference types. Your "y" variable does not store an int, it stores System::Object. The compiler automatically generates a boxing instruction when you assign it. Console::WriteLine() has otherwise no problem displaying the value of an object that's a boxed int.

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

The rule of thumb: use the hat when it is a class object, omit it for simple value types. Avoid the stack semantics of a reference type (omitting the hat so it automatically calls the destructor when the scope ends) until you really grok the difference between value and reference types and why Dispose() is important.

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

#2


Side effect of using WriteLine.

使用WriteLine的副作用。

just 'y' is being treated like an 'object reference' and probably being interrogated for IFormattable, and then having ToString() called on it. '*y' is passing an int.

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

To test this, make another function call Foo(int ^) and see what you are allowed to pass in, and then change it to 'Foo(int)'.

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

I think you are just getting fooled by the 'varargs' nature of WriteLine.

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

#3


Don't rely on WriteLine to tell you what *y and y are, run it from the debugger and inspect *y and y yourself to see the difference.

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

#4


Think of handles to value types as being like a smart handle you might have written yourself, which has operator overloading for conversions. That way, using the handle where you can supply an int would work (via the conversion operator) as well as dereferencing the handle to get the int contained in the object.

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

With regards to Writeline, I think of it as being like the stream output operators where many conversions are implicitly invoked. Just as you might safely go cout << y, you can write System::Console::WriteLine(y).

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

#1


It's a bit sad that C++/CLI allows this syntax. The int type is a value type, the hat is used for reference types. Your "y" variable does not store an int, it stores System::Object. The compiler automatically generates a boxing instruction when you assign it. Console::WriteLine() has otherwise no problem displaying the value of an object that's a boxed int.

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

The rule of thumb: use the hat when it is a class object, omit it for simple value types. Avoid the stack semantics of a reference type (omitting the hat so it automatically calls the destructor when the scope ends) until you really grok the difference between value and reference types and why Dispose() is important.

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

#2


Side effect of using WriteLine.

使用WriteLine的副作用。

just 'y' is being treated like an 'object reference' and probably being interrogated for IFormattable, and then having ToString() called on it. '*y' is passing an int.

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

To test this, make another function call Foo(int ^) and see what you are allowed to pass in, and then change it to 'Foo(int)'.

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

I think you are just getting fooled by the 'varargs' nature of WriteLine.

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

#3


Don't rely on WriteLine to tell you what *y and y are, run it from the debugger and inspect *y and y yourself to see the difference.

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

#4


Think of handles to value types as being like a smart handle you might have written yourself, which has operator overloading for conversions. That way, using the handle where you can supply an int would work (via the conversion operator) as well as dereferencing the handle to get the int contained in the object.

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

With regards to Writeline, I think of it as being like the stream output operators where many conversions are implicitly invoked. Just as you might safely go cout << y, you can write System::Console::WriteLine(y).

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