.NET世界では managed object をインスタンス化するのに new します。
Foo f = new Foo(123); // みたいに。
C++/CLI では Foo^ f = gcnew Foo(123); ってインスタンシエーションは
もちろんのこと、C++の流儀に合わせてautomaticにインスタンスが作れます。
Foo f(123); // なんてな。
実はこれautomaticでもなんでもなく、内部でコソーリ gcnew し、
スコープから外れるときにコソーリ delete しておりますです。
なんちゃってautomatic なのね。
// Foo f(123); は↓と同じ
Foo^ rf = gcnew Foo(123);
...
delete rf;
// C++/CLIでのデストラクタ Foo::~Foo();は Dispose() に相当します。
で、Foo f(123); してあるとき、fのハンドルは %f で得られます。
なもんだから、
void func(List<Foo^>^ container) {
Foo f(123);
container->Add(%f);
}
みたいに なんちゃってautomatic なインスタンスハンドルを関数の外に
放りだすことができちゃいます。コンパイル時にはエラーとはなりません。
が!!
関数 func から抜ける直前に f のデストラクタが動いちゃうですから、
その瞬間関数外に追い出したインスタンスは使い物になりません。
こんなマネすることはないとは思うけど、気を付けましょうね♪
using namespace System;
ref class Foo {
int n_;
public:
Foo(int n);
~Foo();
int get() { return n_; }
};
Foo::Foo(int n) : n_(n) {
Console::WriteLine(L"Foo::ctor({0})", n_);
}
Foo::~Foo() {
Console::WriteLine(L"Foo::dtor() member var. is no more valid");
n_ = -1; // デストラクトされたシルシ
}
using namespace System::Collections::Generic;
void func(List<Foo^>^ container) {
Console::WriteLine(L"enter ::f()");
Foo aFoo(123);
Foo^ rf = %aFoo;
Console::WriteLine(L"aFoo.get() returns {0}", rf->get());
container->Add(rf);
Console::WriteLine(L"exit ::f()");
}
int main() {
List<Foo^> container;
func(%container);
Console::WriteLine(L"back to main");
for each ( Foo^ item in container ) {
Console::WriteLine(L"item->get() returns {0}", item->get());
}
}
// 実行結果
enter ::f()
Foo::ctor(123)
aFoo.get() returns 123
exit ::f()
Foo::dtor() member var. is no more valid
back to main
item->get() returns -1