意外に、C++/CLIで検索する方がいるようなので、
C++/CLIを始めたときに混乱していたネタを投下します。
C++/CLIを始めてから、よくわからない印象を持ったのが文字列の扱いです。
ハンドル型なのに実体のような動きをする存在で、不思議に見えました
System::String ^str1 = gcnew System::String("abc");
System::String ^tmpstr = str1;
Console::WriteLine(str1);
Console::WriteLine(tmpstr);
str1 = gcnew System::String(str1 + "def");
Console::WriteLine(str1);
Console::WriteLine(tmpstr);
初期化はchar*と同じようにできますが、なぜか足し算もできます。
演算子オーバーロードでうまくやっているんでしょうと理解していました。
そして、いちばん混乱したのがこれ。
System::String ^str1 ="abc";
System::String ^tmpstr = str1;
Console::WriteLine(str1);
Console::WriteLine(tmpstr);
str1 += "def";
Console::WriteLine(str1);
Console::WriteLine(tmpstr);
もし、char *のように振舞うのであれば、
2回目のWriteLineでは両方とも"abcdef"が出力されないといけませんが、
実際には、str1は"abcdef"、tmpstrは"abc"と出力されます。
しかし、ハンドル型なので実体を持ち運んでいるわけではないはず。
Stringだけ特殊な扱いを受けている??
どうにも解せないときに出会ったキーワードが以下の2つ。
・ボックス化
・String不変
キーワードにしたがって、上のソースを書きなおしてみます。
System::String ^str1 = gcnew System::String("abc");
System::String ^tmpstr = str1;
Console::WriteLine(str1);
Console::WriteLine(tmpstr);
str1 = gcnew System::String(str1 + "def");
Console::WriteLine(str1);
Console::WriteLine(tmpstr);
まず最初の変数初期化ですが、ボックス化によりgcnewが付与されます。
ですから、char*のように先頭ポインタだけを指しているわけではありません。
そして、+=演算子。
これがもう一つのString不変です。
Stringの内容が変化を受ける場合、そのつど新しい領域が確保されます。
ですから、後半のstr1とtmpstrでは指しているアドレスが違うわけでです。
String不変の観点でSystem::Stringを調べてみると、
ハンドル型の変数を書き換えられない状況では、ReadOnlyになっています。
(たとえば、[]演算子)
StringはUnicodeを格納するクラスなので、char*やstd::stringとは違い、
固定文字列を持ち運ぶもの、と理解しておくといいでしょう。