Как вы относитесь к ручкам в C ++ / CLI? - PullRequest
2 голосов
/ 22 января 2009

Я знаю, что тоже не совсем правильно спрашиваю. Пожалуйста, помогите мне лучше сформулировать мой вопрос.

Мне тяжело складывать мысли вокруг ручек - в некотором смысле это похоже на указатели. Но, в отличие от указателей, похоже, что я могу присваивать значения непосредственно переменной дескриптора, и это влияет на базовое значение данных, а не на сам дескриптор.

Тестовый код ясно показывает, что я получаю одно и то же значение, использую ли я дескриптор или «разыменую» дескриптор, чтобы добраться до данных. Очевидно, что это не будет работать с неуправляемыми указателями. Что я не понимаю?

#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, возможно, сделал разыменование для меня, но я бы ожидал, что статическое приведение к долго не будет. Это также относится к автонавангу?

Ответы [ 4 ]

5 голосов
/ 22 января 2009

Немного грустно, что C ++ / CLI допускает этот синтаксис. Тип int является типом значения, шляпа используется для ссылочных типов. Ваша переменная "y" не хранит int, она хранит System :: Object. Компилятор автоматически генерирует инструкцию по боксу, когда вы ее назначаете. В противном случае Console :: WriteLine () не имеет проблем с отображением значения объекта в штучной упаковке.

Практическое правило: используйте шляпу, когда это объект класса, опустите его для простых типов значений. Избегайте семантики стека ссылочного типа (опуская шляпу, чтобы он автоматически вызывал деструктор, когда заканчивается область), пока вы действительно не заметите разницу между типом значения и ссылочным типом и почему важно Dispose ().

2 голосов
/ 22 января 2009

Не полагайтесь на WriteLine, чтобы сообщить вам, что такое * y и y, запустите его из отладчика и самостоятельно проверьте * y и y, чтобы увидеть разницу.

2 голосов
/ 22 января 2009

Побочный эффект от использования WriteLine.

просто 'y' обрабатывается как 'ссылка на объект' и, вероятно, запрашивается для IFormattable, а затем вызывается ToString () для него. '* y' передает int.

Чтобы проверить это, вызовите еще одну функцию Foo (int ^) и посмотрите, что вам разрешено передавать, а затем измените ее на 'Foo (int)'.

Я думаю, вы просто одурачены "varargs" природой WriteLine.

0 голосов
/ 26 января 2009

Думайте о дескрипторах для типов значений как об умном дескрипторе, который вы могли бы написать сами, у которого есть перегрузка операторов для преобразований. Таким образом, использование дескриптора, в котором вы можете указать int, будет работать (через оператор преобразования), а также разыменовывать дескриптор для получения int, содержащегося в объекте.

Что касается Writeline, я думаю, что он похож на операторы потокового вывода, где неявно вызываются многие преобразования. Точно так же, как вы могли бы спокойно перейти к cout << y, вы можете написать System :: Console :: WriteLine (y). </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...