C ++ / CLI


C++/CLI

C ++ / CLI(共通言語インフラストラクチャ用に変更されたC ++ )は、Microsoftによって作成された言語仕様であり、C ++のマネージ拡張に取って代わります。これは完全なリビジョンであり、現在は非推奨のマネージC ++構文を簡素化し、C#などのMicrosoft.NET言語との相互運用性を提供します。C ++ / CLIは、EcmaによってECMA-372として標準化されました。現在、Expressエディションを含め、Visual Studio 2005、2008、2010、2012、2013、2015、2017、2019、および2022で使用できます。
C ++ / CLI
パラダイム
構造化された、命令型の、オブジェクト指向
家族 C によって設計された
マイクロソフト
デベロッパー
マイクロソフト
初登場
2005 ; 16年前 (2005)
安定リリース
標準ECMA-372 / 2005年12月 ; 16年前  (2005-12)
プラットホーム
共通言語インフラストラクチャ
Webサイト
www .ecma-international .org / publications / standard / Ecma-372 .htm
に影響を受けた
C ++、C ++のマネージ拡張、C#

コンテンツ
1 構文の変更
1.1 ハンドル 1.2 参照の追跡 1.3 ファイナライザーと自動変数
2 演算子のオーバーロード
3 C ++ / C#の相互運用性
4 C ++ / CX
5 参考文献
6 外部リンク

構文の変更
C ++ / CLIは、(例えば、キーワードの新しいセットを持つ)、代わりにC ++スーパーセット指向の独自の言語と考えるべきであるマネージドC ++(非標準のキーワードのようなスタイルました(MC ++)または)。このため、特にあいまいな識別子の削除と.NET固有の機能の追加に関連して、いくつかの主要な構文上の変更が__gc__value
MC ++の演算子の複数のバージョンなど、多くの競合する構文が分割されています。C++ / CLIでは、.NET参照型がnewキーワードで作成されます(つまり、ガベージコレクションされたnew())。また、C ++ / CLIは、.NETからジェネリックスの概念を導入しました(最も一般的な目的では、標準のC ++テンプレートに似ていますが、実装がまったく異なります)。new()gcnew

ハンドル
MC ++には、2つの異なるタイプのポインターがありました。ポインターは通常のC ++ポインターでしたが、ポインターは.NET参照タイプで機能していました。ただし、C ++ / CLIでは、ポインターのタイプは通常のC ++ポインターのみですが、.NET参照タイプは、(ではなく)新しい構文を使用して「ハンドル」を介してアクセスされます。この新しい構成は、管理対象と標準のC ++コードが混在している場合に特に役立ちます。どのオブジェクトが.NET自動ガベージコレクションの下にあり、プログラマーが明示的に破棄することを覚えておく必要があるオブジェクトを明確にします。__nogc__gcClassName^ClassName*

参照の追跡
トラッキング基準C ++ / CLIでは、渡されたバイ参照変数のハンドルです。概念的には、標準のC ++で” “(ポインターへの参照)を使用するのと似ており、(関数宣言で)C#の型に適用される” “キーワード、またはVisual Basic.NETの” “に対応します。C ++ / CLIは、「」構文を使用して、ハンドルへの追跡参照を示します。*&refByRef^%
次のコードは、追跡参照の使用例を示しています。追跡参照を通常のハンドル変数に置き換えると、参照ではなく値によって渡されるため、配列内の文字列ハンドルのコピーのみが設定されるため、結果の文字列配列には初​​期化されていない10個の文字列ハンドルが残ります。
int main () {{ 配列<文字列^> ^ arr = gcnew配列<文字列^> (10 );
int i = 0 ;
for each (String ^%s in arr ){
s = i ++ 。ToString ();
} 0を返す; }
これは、ループが参照によって値を渡すことを許可しないC#では違法であることに注意してしたがって、回避策が必要になります。foreach

ファイナライザーと自動変数
C ++ / CLIのもう1つの変更点は、ガベージコレクションルーチンの一部として実行される特殊なタイプの非決定論的デストラクタであるファイナライザ構文の導入です。C ++デストラクタ構文は、管理対象オブジェクトにも存在し、決定論的破壊の「従来の」C ++セマンティクス(つまり、を使用してユーザーコードで呼び出すことができるデストラクタ)をより適切に反映します。!ClassName()~ClassName()delete
生の.NETパラダイムでは、非決定論的破壊モデルはルートクラスの保護されたメソッドをオーバーライドしますが、決定論的モデルはインターフェイスメソッド(C ++ / CLIコンパイラがデストラクタを変換します)を介して実装されます。DisposeメソッドをオーバーライドするC#またはVB.NETコードのオブジェクトは、C ++ / CLIの.NETクラスと同じように、C ++ / CLIで手動で破棄できます。FinalizeObjectIDisposable Disposedelete
// C ++ / CLI参照クラスMyClass {{パブリック: MyClass (); //コンストラクタ〜MyClass (); //(決定論的)デストラクタ(IDisposable.Dispose()として実装)protected :
!MyClass (); //ファイナライザー(非決定論的デストラクタ)(Finalize()として実装) パブリック: 静的ボイドテスト() {{ MyClass自動; //ハンドルではなく、初期化もありません:コンパイラはここでコンストラクタを呼び出しますMyClass ^ user = gcnew MyClass ();
ユーザーを削除します;
//自動がスコープ外になると、コンパイラは自動のデストラクタを呼び出します} };

演算子のオーバーロード
演算子のオーバーロードは、標準のC ++と同様に機能します。すべての*は^になり、すべての&は%になりますが、重要な追加を除いて、構文の残りの部分は変更されません。.NETクラスの場合、演算子のオーバーロードは、クラス自体だけでなく、それらのクラスへの参照に対しても可能です。この機能は、.NETrefクラスから期待される演算子のオーバーロードのセマンティクスをrefクラスに与えるために必要です。(逆に、これは、.NET Framework refクラスの場合、参照演算子のオーバーロードがC ++ / CLIで暗黙的に実装されることが多いことも意味します。)
たとえば、演算子==を使用して2つの異なる文字列参照(String ^)を比較すると、2つの文字列が等しい場合は常にtrueになります。ただし、演​​算子のオーバーロードは静的です。したがって、Object ^にキャストすると、オーバーロードセマンティクスが削除されます。
//参照演算子のオーバーロードの影響String ^ s1 = “abc” ; 文字列^ s2 = “ab” + “c” ; オブジェクト^ o1 = s1 ; オブジェクト^ o2 = s2 ; s1 == s2 ; // true o1 == o2 ; // false

C ++ / C#の相互運用性
C ++ / CLIを使用すると、C ++プログラムでC#DLLのC#プログラムを使用できます。ここで、#usingキーワードは、コンパイルメタデータ用にDLLが配置されているコンパイラを示します。この単純な例では、データのマーシャリングは必要ありません。
#include “stdafx.h” 名前空間システムを使用する; #using “… MyCS.dll”int main (array < System :: String ^> ^ args ){
double x = MyCS :: Class1 :: add (40.1、1.9 ); _
0を返す; }
MyCS.DLLのC#ソースコードコンテンツ。
名前空間 MyCS { public class Class1 {
public static double add (double a 、 double b ) {
return a + b ;
} } }
この例は、文字列がC ++文字列からC#から呼び出し可能な文字列にマーシャリングされ、次にC ++文字列に戻る方法を示しています。文字列マーシャリングは、文字列の内容をさまざまな環境で使用できるフォームにコピーします。
#include <文字列> #include #include #include “stdafx.h” 名前空間システムを使用する; #using “..MyCS.dll”int main (){ std :: string s = “私は猫です” ; システム::文字列^ clrString = msclr ::相互運用:: marshal_as <システム::文字列^> (s ); // C#システムから使用可能な文字列:: String ^ t = MyCS :: Class1 :: process (clrString ); // C#関数を呼び出しますstd :: string cppString = msclr :: interop :: marshal_as < std :: string > (t ); // C ++ stdから使用可能な文字列:: cout << "Hello、C ++ / C#Interop!" << std :: endl ; std :: cout << cppString << std :: endl ; 0を返す; }
C#コードはC ++に対応し
名前空間MyCS { public class Class1 {
public static string process (string a ) {
returna 。(”cat” 、”dog” )+ “をしっぽに置き換えます” ; } } }
C ++ / C#の相互運用性により、C ++は.NET機能の全世界に簡単にアクセスできます。

C ++ / CX
WinRTを対象とするC ++ / CXは、完全にアンマネージコードを生成しますが、 COM「オブジェクト」に類似したWinRTの参照カウントコンポーネントのrefおよび^構文を借用します。

参考文献
^ ++構文アップグレードチェックリストのマネージ拡張-MSDNライブラリ ^ C ++相互運用機能の使用(暗黙のPInvoke)
^ C ++ / CXデザインの内部-VisualC ++チームブログ-サイトホーム-MSDNブログ

外部リンク
ECMA 372:C ++ / CLI言語仕様
ハーブサッター:C ++ / CLIキーワード:内部
ハーブサッター:C ++ / CLIの理論的根拠
C ++ / CLIのMSDNドキュメント
キーワードの空白に関する特許出願
C ++ / CLIに関するBjarneStroustrup(C ++の設計者/作成者)の見解
スタンリーB.リップマン:こんにちは、C ++ / CLI
Stanley B. Lippman:C ++ / CLIがCLIタイプのテンプレートとCLI汎用メカニズムの両方をサポートする理由