2012-01-18 4 views
0
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을 사용해야합니다.이 관리 객체는 어디에 저장됩니까?

답변

1

그냥 값 형식에 대한 참조 유형의 멤버 추가

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

... 
ValBase* = new ValBase; 

을 그리고 컴파일러가 저장된 정확한 위치를 알려줍니다 :

오류 C3255를 : ' ValBase ':이 힙 유형의 객체를 원시 힙에 동적으로 할당 할 수 없습니다.

의미 체계는 충분히 간단합니다. 결국 스택에 값 유형을 저장할 수 있습니다. 스택에 올라갈 수 있으면 원시 힙으로 이동할 수 있습니다. 어쨌든 가비지 컬렉터가 찾아야 할 객체가 포함되어 있지 않은 한. 그래서 C3255가 있습니다. .NET Framework에는 값 유형이 있으므로 스택에 물건을 저장하는 것이 값 싸고 코드를 효율적으로 만듭니다.

하지만 그냥 정확히 유용 그렇게하지 않습니다 네이티브 힙에 저장하기 때문이다. ValBase^ ValBase1 = gcnew ValBase;에 대해서도 마찬가지이며, 박스형 값을 관리되는 힙에 저장합니다. System :: Object에 포함 된 값의 복사본입니다. 그것은 가치 유형이 개체에서 상속하는 척 수 있기 때문에 권투는 매우 유용합니다. 그러나 싸구려가 아니며, 정당한 이유없이 당신이하고 싶지 않은 어떤 것도 결코 아닙니다.

+0

* 다른 질문입니다. 새로운 질문으로 주저하지 마십시오. –

2

두 번째 질문 : 예, C++/CLI에서 값 유형을 사용하는 경우 ^을 제거해야합니다. 효율성 향상이 많다는 것을 나는 알지 못합니다.하지만 이것이 가치 유형의 표준입니다.

ValBase valBase1;은 C# 코드 ValBase valBase1 = new ValBase();에 해당하는 C++/CLI입니다. C++/CLI 코드 ValBase^ valBase1에 해당하는 C#은 없습니다. 값 유형에 ^을 사용하면 ValBase^ValBase이 다른 유형이므로 .NET API를 호출하는 데 문제가 있음을 알 수 있습니다.

값 유형에 기본값이 아닌 생성자를 호출해야하는 경우 다음 구문을 참조하십시오. 힙 할당 (관리 또는 비 관리)이 없으므로 new 또는 gcnew이 없으므로 생성자를 직접 호출하면됩니다.

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

또한 참조 유형에 ^을 제거 할 수 있습니다, 그것은 시도 - 마지막-처분 블록에 컴파일됩니다. 예 :

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(); 
} 
관련 문제