Visual Studio 2010 Bata 1入れたにも関わらず、C# 4.0関係の実験はまだしてないよねと気付いたが、
まぁ今はC++ばっかり使っているのでC++0xの実験だけでいいじゃないとは思った。
いやね、C# 4.0ってそんなに魅力的な拡張ってないのよね。dynamicとか僕はあんまり使わないだろうし。
ライブラリの拡張があるかもしれんが、まぁその辺は情報持ってないからね。
++C++にはあんまりそういうネタはないのですが、まぁちょっとずつ調べていくか。
前にいろいろ試していたとき、boost::scoped_ptrは編入されなかったのかと思っていたのですが、
実はstd::auto_ptrと合併してstd::unique_ptrとして新しく追加されていることに気付きました。
これに伴い、評判のよろしくなかったstd::auto_ptrは非推奨となるようです。
結構いろいろなことができそうです。
まず、boost::scoped_ptr的な側面を辿ってみた。
#include <iostream>
#include <memory>
#include <string>
class MyObj{
public:
int ID;
MyObj(int id):ID(id){
std::cout << "Create MyObj : " << this->ID << std::endl;
}
MyObj(const MyObj& other):ID(other.ID){
std::cout << "Copy MyObj : " << this->ID << std::endl;
}
MyObj(MyObj&& other):ID(other.ID){
std::cout << "Move MyObj : " << this->ID << std::endl;
}
~MyObj(void){
std::cout << "Destroy MyObj : " << this->ID << std::endl;
}
};
int main(void){
{
std::unique_ptr<MyObj> x(new MyObj(10));
std::unique_ptr<MyObj> y;
y.reset(new MyObj(20));
x.swap(y);
y.reset(new MyObj(30));
std::cout << "x->ID : " << x->ID << std::endl;
std::cout << "y->ID : " << y->ID << std::endl;
}
{char dummy; std::cin >> dummy;}
return 0;
}
破棄などの状況が見やすいようにMyObjとかいうクラスを用意してみた。
そういえば、Visual Studio以外ではmainの返り値ってvoidは許されないんだね。
GCCでそうだったわけですが、intとするのが無難ですよね。
scoped_ptrはswapとresetによりさすポインタを操作できるんですね。
実はこの機能があるのでスコープ内で完結するならばstd::auto_ptrと同等の能力はあったわけですよ。
今回はyを後でresetで設定して、xとyを入れ替えて、yを新しいオブジェクトでresetしてるので、
xはnew MyObj(20)で作ったオブジェクト、yはnew MyObj(30)で作ったオブジェクト、new MyObj(10)のオブジェクトはreset時消えた。
ということが実行して理解できるはず。
けどboost::scoped_ptrは一切のコピーコンストラクタを持たないから返り値にはできない。
あと、所有権を放棄するreleaseとかはない。別にscoped_ptrならあってもよかったと思うけど。
だからこういうことすらできない。
MyObj* Create(void){
boost::scoped_ptr<MyObj> p(new MyObj(20));
return p.release();
}
この辺がstd::auto_ptrとの違いで棲み分けだったわけです。
それができるstd::auto_ptrは破壊的コピーするとかいう問題もあったと。
実は破壊的コピーの問題について解決する方法が見つかったというのがこのunique_ptrのきっかけじゃないかなと。
というのは右辺値参照のことですね。(参考記事 : C++0xの化け物じみた右辺値参照)
これを使えば、関数の返り値など右辺値は破壊的コピーができて、
そして左辺値であっても std::move() にかぶせれば破壊的コピーができるわけです。
これ使えるぞと思ったんでしょう。その結果std::unique_ptrが誕生したということになります。
std::unique_ptr<MyObj> Create(void){
std::unique_ptr<MyObj> p(new MyObj(20));
return p;
}
//本体
std::unique_ptr<MyObj> x=Create();
std::unique_ptr<MyObj> y=std::move(x);
if(x==0) std::cout << "x is null" << std::endl;
std::cout << "y->ID : " << y->ID << std::endl;
移動がはっきりするようになりましたし、swapとかresetとかもあるし便利ですね。
なお、破壊的以外のコピーができないのは相変わらずです。
基本的にはコピー不可だけど、右辺値またはstd::move()をかぶせた場合は可ということです。
なのでもちろんstd::vectorには入れられません。
しかしこういうときはstd::shared_ptrを使うので問題ありませんね。