書けば書くほどABとどこも似ていないとしか思えなくなりますが、まだまだ続きます。そんなC++/CLI第3回目は、前回に続きC++/CLIの何でもありな具合を見せてくれる追跡参照を取り上げます。
ご存知のとおり、C++には参照というものがあります。
int i; int& r = i; int* p = new int; int& r2 = *p; |
ポインタがハンドルになったように、参照に対応するものとして追跡参照というものが導入されました。%を使います。
Object^ obj = gcnew Object; Object% ref = *obj; Object o; //Objectは参照型ですがこんなことができます。詳しくは次回 Object% r = o; Object^ h = %o; Object^ h2 = %r; |
ハンドルから参照を得る演算子は*であるのに対し、左辺値からハンドルを得る演算子が%になっている点は、一見奇妙ですが、きちんとわけがあります。しかし、それは次回以降の話です。
追跡参照とは、CLIのガベージコレクションでは、インスタンスのメモリ位置が移動されることがあるので、GC時にそれを追跡するということに由来します。ハンドルも追跡ハンドルと呼ばれることがあります。
もちろん追跡参照は値型に対しても区別無く使用できます。更にスタックやネイティブヒープ上にあるものなど、GC対象外のインスタンスを参照することすらできます。このように何でもありです。
int i; int% r1 = i; int& r = i; int% r2 = r; int *p = new int; int% r3 = *p; int^ h = gcnew int; int% h4 = *h; |
前に書いたようにハンドルではボックス化されましたが、追跡参照ではそうなりません。ポインタ・ハンドルと違い、追跡参照は正にC++参照のマネージ版に徹していると感じます。
#include <iostream> int main() { int i = 1, j = 7; int^ h = i; int% r = j; h = 11; r = 77; std::cout << *h << ' ' << r << std::endl; std::cout << i << ' ' << j << std::endl; }</code> |
ハンドルへの参照ということも可能です。
#include <iostream> #include <string> void f(std::string*& s) //sは、「std::stringへのポインタ」への参照 { s = new std::string("hello, "); } void f(System::String^% s) //sは、「System::Stringへのハンドル」への追跡参照 { s = gcnew System::String("world."); } int main() { std::string* s; f(s); std::cout << *s << std::flush; delete s; System::String^ s2; f(s2); System::Console::WriteLine(s2); } |
ハンドルへの参照型が関数の引数で用いられている場合、C#での参照型に対するref/out引数に相当します:方法 : out パラメータを指定する – MSDNライブラリ。なんだかんだいって、これが追跡参照の典型的な利用法の最たるものだと思います。
とまあ、きりがなくなるのでここら辺にしておきます。
スポンサード リンク |
この記事のカテゴリ
- C++/CLI ⇒ C++/CLI (3) 追跡参照 〜いつも追跡するとは限らない〜