C++ cli 此托管对象存储在哪里? 值类ValBase { 公众: INTA; }; ref类RefBase { 公众: INTA; }; int main(数组^args) { RefBase ^RefBase1=gcnew RefBase;//在CLR堆上创建的合法.Ref类型的托管对象。 ValBase ^ValBase1=gcnew ValBase;//在CLR堆上创建的合法.Value类型托管Obj。 RefBase*RefBase2=new RefBase;//非法:new不能用于托管Ref类 ValBase*ValBase2=new ValBase;//这可以编译,但这个“托管对象”存储在哪里?CLR堆还是本机堆? }

C++ cli 此托管对象存储在哪里? 值类ValBase { 公众: INTA; }; ref类RefBase { 公众: INTA; }; int main(数组^args) { RefBase ^RefBase1=gcnew RefBase;//在CLR堆上创建的合法.Ref类型的托管对象。 ValBase ^ValBase1=gcnew ValBase;//在CLR堆上创建的合法.Value类型托管Obj。 RefBase*RefBase2=new RefBase;//非法:new不能用于托管Ref类 ValBase*ValBase2=new ValBase;//这可以编译,但这个“托管对象”存储在哪里?CLR堆还是本机堆? },c++-cli,C++ Cli,在上一次分配中,托管对象存储在哪里?我对C++ CLI完全陌生。另外,值类型是否应该使用堆栈语义来提高代码效率?i、 e我应该使用ValBase ValBase1,而不是ValBase^ValBase1=gcnew ValBase 至于第二个问题:是的,在C++/CLI中使用值类型时,应该删除^。我不知道有多少效率提升,但这是价值类型的标准 ValBase-valBase1是C++/CLI与C#codeValBase valBase1=new ValBase()等价的吗。没有C++等价于C++/

在上一次分配中,托管对象存储在哪里?我对C++ CLI完全陌生。另外,值类型是否应该使用堆栈语义来提高代码效率?i、 e我应该使用ValBase ValBase1,而不是ValBase^ValBase1=gcnew ValBase

至于第二个问题:是的,在C++/CLI中使用值类型时,应该删除
^
。我不知道有多少效率提升,但这是价值类型的标准

ValBase-valBase1
是C++/CLI与C#code
ValBase valBase1=new ValBase()等价的吗。没有C++等价于C++/CLI代码
ValBase^valBase1
。如果对值类型使用
^
,您会发现调用.NET API时遇到问题,因为
ValBase^
ValBase
是不同的类型

如果需要对值类型调用非默认构造函数,则语法如下。由于没有堆分配(托管或非托管),因此没有
new
gcnew
,只需直接调用构造函数即可

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 ? 

}
您还可以删除引用类型上的
^
,这将编译为try-finally-dispose块。例如:

ValueTypeFoo foo = ValueTypeFoo("bar", "baz");
StringBuilder sb;
某人附加(“foo”);
使某人返回字符串();
//相当于:
StringBuilder ^sb=nullptr;
尝试
{
sb=gcnew StringBuilder();
sb->Append(“foo”);
返回sb->ToString();
}
最后
{
IDisposable ^disp=动态播放(sb);
如果(disp!=nullptr)disp->Dispose();
}

至于第二个问题:是的,在C++/CLI中使用值类型时,应该删除
^
。我不知道有多少效率提升,但这是价值类型的标准

ValBase-valBase1
是C++/CLI与C#code
ValBase valBase1=new ValBase()等价的吗。没有C++等价于C++/CLI代码
ValBase^valBase1
。如果对值类型使用
^
,您会发现调用.NET API时遇到问题,因为
ValBase^
ValBase
是不同的类型

如果需要对值类型调用非默认构造函数,则语法如下。由于没有堆分配(托管或非托管),因此没有
new
gcnew
,只需直接调用构造函数即可

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 ? 

}
您还可以删除引用类型上的
^
,这将编译为try-finally-dispose块。例如:

ValueTypeFoo foo = ValueTypeFoo("bar", "baz");
StringBuilder sb;
某人附加(“foo”);
使某人返回字符串();
//相当于:
StringBuilder ^sb=nullptr;
尝试
{
sb=gcnew StringBuilder();
sb->Append(“foo”);
返回sb->ToString();
}
最后
{
IDisposable ^disp=动态播放(sb);
如果(disp!=nullptr)disp->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();
}
编译器会准确地告诉您它的存储位置:

错误C3255:“ValBase”:无法在本机堆上动态分配此值类型对象

语义非常简单,毕竟您可以在堆栈上存储值类型。如果它可以放在堆栈上,那么它也可以放在本机堆上。只要它不包含需要垃圾回收器找到的对象。这就是为什么会有C3255。正是由于这个原因,.NET framework中存在值类型,在堆栈上存储内容既便宜又能提高代码效率


但仅仅因为可以将其存储在本机堆上,并不意味着这样做完全有用。
ValBase^ValBase1=gcnewvalbase也是如此,它在托管堆上存储装箱值。嵌入在System::Object中的值的副本。装箱非常有用,因为它允许假装值类型从对象继承。但是它并不便宜,从来都不是你没有理由想做的事情。

只需在值类型中添加引用类型的成员即可:

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();
}
编译器会准确地告诉您它的存储位置:

错误C3255:“ValBase”:无法在本机堆上动态分配此值类型对象

语义非常简单,毕竟您可以在堆栈上存储值类型。如果它可以放在堆栈上,那么它也可以放在本机堆上。只要它不包含需要垃圾回收器找到的对象。这就是为什么会有C3255。正是由于这个原因,.NET framework中存在值类型,在堆栈上存储内容既便宜又能提高代码效率

但仅仅因为可以将其存储在本机堆上,并不意味着这样做完全有用。
ValBase^ValBase1=gcnewvalbase也是如此,它在托管堆上存储装箱值。嵌入在System::Object中的值的副本。装箱非常有用,因为它允许假装值类型从对象继承。但它并不便宜,从来都不是你无缘无故想做的事情。

这是另一个问题,不要犹豫在新问题中问它。这是另一个问题,不要犹豫在新问题中问它。