微軟推出 VS.NET 2003 實現 Managed C++ 時,開發者反應兩極:雖欣慰可繼續使用 C++,但雙底線語法 (__gc, __property 等) 晦澀難讀。微軟遂於 2003 年 10 月在 ECMA 推動 C++/CLI 標準制定,由 VS 2005 編譯器支援,旨在提供優雅、自然的 CLI 程式設計體驗。
*,行為卻截然不同。using namespace System;
void _tmain() {
Console::WriteLine("Hello World");
}
無需手動引用 mscorlib.dll,/clr 編譯會自動處理 (預設 /clr:newSyntax)。
Managed C++ 最大混淆在於 * 同時代表原生指標與托管參考。C++/CLI 引入 控制代碼 (Handle),以 ^ 符號宣告:
void _tmain() {
String^ str = "Hello World"; // ^ 看起來像帽子
Console::WriteLine(str);
}
^ 代表 CLI 托管物件的參考,相當於舊語法的 __gc*。控制代碼與指標在本質上完全不同:
| 特性 | 指標 (*) | 控制代碼 (^) |
|---|---|---|
| 指向 | 記憶體位址 | 托管堆上物件 |
| GC 影響 | 不受影響 | 物件移動時自動更新 |
| 記憶體管理 | 手動 delete | GC 自動回收,可選擇性 delete |
| 型別安全 | 可指向 void* | 必須指向具體型別,不可為 void^ |
| 實例化 | new | gcnew 回傳控制代碼 |
void _tmain() {
String^ str = gcnew String("Hello World");
Object^ o1 = gcnew Object();
Console::WriteLine(str);
}
gcnew 關鍵字明確區分托管與非托管實例化。
CLR 類型使用形容詞前綴區分種類:
ref class, ref structvalue class, value structinterface class, interface structenum class, enum structclass, struct (無前綴)using namespace System;
interface class IDog { void Bark(); };
ref class Dog : IDog {
public:
void Bark() { Console::WriteLine("Bow wow wow"); }
};
void _tmain() {
Dog^ d = gcnew Dog();
d->Bark();
}
舊語法需 __gc, __interface 等關鍵字,新語法極度簡潔。
Object^ o = 44; (型別安全)int y = *reinterpret_cast<int^>(o);裝箱建立物件副本,原值型別變更不影響已裝箱物件。裝箱物件保留原始型別資訊,拆箱時型別不符會拋出 InvalidCastException。