こんにちは。きんくまです。
C++をやってます。
前にもやったことがあって、基本的な文法や使い方はわかっていたのだけど、細かいところを知らなくてあわあわしてます。
それで、オブジェクトをnewしたらdeleteが基本!みたいに覚えていたんですが、最近はスマートポインタというのがあるみたいです。
C++11という規格があって、そこに以前からあったBoostっていうライブラリで使われてた機能を盛り込んだみたい(違ってたらごめんなさい)。
Boostはなんかすごい便利みたいなんだけど、使ったことないからわかんないです、、。
で、スマートポインタです。
スマートポインタ
ここのページがすごくわかりやすかったです。
>> EZ-NET: C++11 でスマートポインタを使用する – C++ プログラミング
ポインタを自分でdeleteしなくても、所有者(owner)がいなくなったら勝手に破棄してくれるという。
、、ん?これってObjective-Cのリファレンスカウンタじゃ??
どっちが先かわかりませんが、そんな印象。
shared_ptrはObjective-CのARC前でいう autorelease
unique_ptrは所有者一人のretain
weak_ptrはassign
みたいな印象でした。
あとauto_ptrっていうのもあって、それは非推奨らしい。
それじゃあ、試しに挙動チェックしてみようと思い、ツリー構造をもたせた表示オブジェクトを作ってみました。
その中で、m_parentという親のスマートポインタをweak_ptrで持たせたかったんですが、そのためには自分自身のweak_ptrをプロパティに持つ必要があります。それで、どうやるのか調べてみたら、staticメソッドでやれば良いみたいでした。なるほど。weak_ptrなのは循環参照してもポインタを解放できるようにするためです。Objective-Cでのassign, weakと使い方はいっしょ。
ソースです。ヘッダーファイル、実装ファイルに分けずに、main.cppに展開しちゃってますけど、サンプルなんですんません、、。
#include <iostream> #include <memory> #include <list> #include <string> class DisplayObject; typedef std::unique_ptr<DisplayObject> DisplayObjectUp; typedef std::shared_ptr<DisplayObject> DisplayObjectSp; typedef std::weak_ptr<DisplayObject> DisplayObjectWp; class DisplayObject{ public: static DisplayObjectSp CreateSp(const std::string name){ DisplayObjectSp obj(new DisplayObject(name)); obj->m_self = obj; return obj; } DisplayObject(const std::string name){ m_name = name; std::cout << m_name << " is constructed" << std::endl; } ~DisplayObject(){ std::cout << m_name << " is destructed" << std::endl; } std::string m_name; DisplayObjectWp m_self; DisplayObjectWp m_parent; std::list<DisplayObjectSp> m_children; void AddChild(const DisplayObjectSp &child){ if(DisplayObjectSp myParent = child->m_parent.lock()){ throw "child is already added"; return; } child->m_parent = m_self; m_children.push_back(child); std::cout << child->m_name << " is added to " << m_self.lock()->m_name << std::endl; } void RemoveChild(const DisplayObjectSp &child){ //auto is same as std::list<DisplayObjectSp>::iterator auto it = m_children.begin(); while (it != m_children.end()) { if(*it == child){ child->m_parent.reset(); m_children.erase(it); std::cout << child->m_name << " is removed from " << m_self.lock()->m_name << std::endl; } it++; } } void Update(){ //do something std::cout << m_name << " is updated" << std::endl; auto it = m_children.begin(); while (it != m_children.end()) { (*it)->Update(); it++; } } }; int main(int argc, const char * argv[]) { DisplayObjectSp parent = DisplayObject::CreateSp("parent"); { DisplayObjectSp child1 = DisplayObject::CreateSp("child 1"); DisplayObjectSp child2 = DisplayObject::CreateSp("child 2"); DisplayObjectSp grandChild = DisplayObject::CreateSp("grandchild"); std::cout << std::endl << "----1" << std::endl; parent->AddChild(child1); parent->AddChild(child2); child1->AddChild(grandChild); std::cout << std::endl << "----2" << std::endl; parent->Update(); std::cout << std::endl << "----3" << std::endl; parent->RemoveChild(child1); } std::cout << std::endl << "----4" << std::endl; return 0; }
実行時の出力
parent is constructed child 1 is constructed child 2 is constructed grandchild is constructed ----1 child 1 is added to parent child 2 is added to parent grandchild is added to child 1 ----2 parent is updated child 1 is updated grandchild is updated child 2 is updated ----3 child 1 is removed from parent child 1 is destructed grandchild is destructed ----4 parent is destructed child 2 is destructed
ソース46行目autoというのが追加されたみたいです。iterator書くのに便利みたいです。
>> でらうま倶楽部 : 今日から始められる C++11 対応!!
その他の便利メソッドなども紹介されてます。
C++なかなかに歯ごたえがある言語ですが、けっこう面白いかも。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ