Где хранится этот управляемый объект? - PullRequest
0 голосов
/ 19 января 2012
value class ValBase
{
  public:
    int a;
};

ref class RefBase
{
public:
     int a;
};

int main(array<System::String ^> ^args)
{

RefBase^ RefBase1 = gcnew RefBase; //LEGAL. Ref type Managed Obj created on CLR heap.
ValBase^ ValBase1 = gcnew ValBase; //LEGAL. Value type Managed Obj created on CLR heap.

RefBase* RefBase2 = new RefBase;   //ILLEGAL: new cannot be used on Managed Ref Class
ValBase* ValBase2 = new ValBase;   //This compiles okay but where is this "Managed Object" stored ? CLR heap or Native heap ? 

}

В последнем назначении где хранится управляемый объект?Я совершенно новичок в C ++ CLI.Кроме того, верно ли, что типы значений должны использовать семантику стека, чтобы сделать код эффективным?т.е. вместо ValBase ^ ValBase1 = gcnew ValBase, я должен просто использовать ValBase ValBase1;

Ответы [ 2 ]

2 голосов
/ 19 января 2012

Что касается вашего второго вопроса: Да, вы должны удалить ^, когда используете типы значений в C ++ / CLI.Я не знаю, что есть большая выгода в эффективности, но это стандарт для типов значений.

ValBase valBase1; - это C ++ / CLI, эквивалентный коду C # ValBase valBase1 = new ValBase();.Не существует C #, эквивалентного коду C ++ / CLI ValBase^ valBase1.Если вы используете ^ для типов значений, вы обнаружите, что у вас возникают проблемы с вызовом .NET API, поскольку ValBase^ и ValBase - это разные типы.

Если вам нужно вызвать неконструктор по умолчанию для типа значения, вот синтаксис.Поскольку нет выделения кучи (управляемой или неуправляемой), нет new или gcnew, просто вызовите конструктор напрямую.

ValueTypeFoo foo = ValueTypeFoo("bar", "baz");

Вы также можете удалить ^ на ссылочных типахэто скомпилируется в блок try-finally-dispose.Пример:

StringBuilder sb;
sb.Append("foo");
return sb.ToString();

// Equivalent to:

StringBuilder^ sb = nullptr;
try
{
    sb = gcnew StringBuilder();
    sb->Append("foo");
    return sb->ToString();
}
finally
{
    IDisposable^ disp = dynamic_cast<IDisposable^>(sb);
    if(disp != nullptr) disp->Dispose();
}
1 голос
/ 19 января 2012

Просто добавьте элемент ссылочного типа к типу значения:

value class ValBase
{
  public:
      String^ s;
      int a;
};

...
ValBase* = new ValBase;

И компилятор точно скажет, где он хранится:

Ошибка C3255: 'ValBase': не может динамически выделить этот объект типа значения в собственной куче

Семантика достаточно проста, ведь вы можете хранить тип значения в стеке.Если он может помещаться в стек, то он также может помещаться в собственную кучу.Пока он не содержит объектов, которые в любом случае должны быть найдены сборщиком мусора.Вот почему C3255 есть.По этой причине в .NET Framework существуют типы значений, поэтому хранение содержимого в стеке обходится дешево и делает код эффективным.

Но только потому, что можно сохранить его в собственной кучене делает это полезным , чтобы сделать это.То же самое верно для ValBase^ ValBase1 = gcnew ValBase;, который хранит значение в штучной упаковке в управляемой куче.Копия значения, встроенного в System :: Object.Бокс очень полезен, потому что позволяет делать вид, что типы значений наследуются от Object.Но это не дешево, никогда то, что вы хотели бы сделать без веской причины.

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