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完全陌生。另外,值类型是否应该使用堆栈语义来提高代码效率?i、 e我应该使用ValBase ValBase1,而不是ValBase^ValBase1=gcnew ValBase 至于第二个问题:是的,在C++/CLI中使用值类型时,应该删除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++/
^
。我不知道有多少效率提升,但这是价值类型的标准
ValBase-valBase1
是C++/CLI与C#codeValBase 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#codeValBase 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中的值的副本。装箱非常有用,因为它允许假装值类型从对象继承。但它并不便宜,从来都不是你无缘无故想做的事情。这是另一个问题,不要犹豫在新问题中问它。这是另一个问题,不要犹豫在新问题中问它。