スマポだよ!スマポ!ナマポまだ使ってんの?ぷぷぷ(๑˃̵ᴗ˂̵)و
大半の用途でスマポに置換えるべきだと最近思います。
布教もかねて、C++ってアレだよね?レガシーなあれだよね?
と思われている方もいると思いますが……誤解です。
確かにC++03までだと古臭い言語という感じがしますが、
C++11からそんなことなくなっています。
Javaのほうがむしろ古臭くなってしまっています。
簡単なサンプルコードで比較してみます。
C++03まで
#include <iostream> #include <vector> #include <string> struct CTest { int foo; int bar; CTest(int f, int b) : foo(f), bar(b) { } }; int main() { using namespace std; vector<CTest *> ct; ct.push_back(new CTest (10, 20)); ct.push_back(new CTest (11, 21)); ct.push_back(new CTest (12, 22)); for (vector<CTest *>::iterator it = ct.begin(); it != ct.end(); ++it) { cout << (*it)->foo << "," << (*it)->bar << endl; } for (vector<CTest *>::iterator it = ct.begin(); it != ct.end(); ++it) { delete *it; *it = NULL; } return 0; }
なんともvectorをpush_backで入れてnewしないといけないあたりや
iteratorがものすごくめんどくさい(;´・ω・)
しかも他の言語からきた人は(*it)->foo
とか
なんだこのシンタックスと思うに違いない。
C++11から
同じコードを書く場合(生ポインタ)を使う場合、だいぶましに書けるようになりました。
#include <iostream> #include <vector> #include <string> struct CTest { int foo; int bar; // 今回の例では引数を取るコンストラクタはいらない }; int main() { using namespace std; // メンバ初期化リストを利用 vector<CTest *> ct { new CTest {10, 20}, new CTest {11, 21}, new CTest {12, 22}, }; for (const auto c : ct) { cout << c->foo << "," << c->bar << endl; } for (auto c : ct) { delete c; c = nullptr; } return 0; }
だいぶすっきりしましたね。メンバ初期化リスト大活躍。
さらに、型推論も便利。
んで、ここでconst auto c
の部分なのですが、
この推論はポインタまでやってくれるらしく*1、*
は不要ですが、別に書いてもいいことになっているらしい。const auto *c
でも意味は同じみたいな。
stackoverflow.com
スマートポインタを使った例
本題のスマポ
スマートポインタの中でも扱いやすいshared_ptrを使ってみます。
#include <iostream> #include <vector> #include <string> #include <memory> // shared_ptr struct CTest { int foo; int bar; CTest(int f, int b) : foo(f), bar(b) { } }; int main() { using namespace std; // 参照カウンタ方式のshared_ptr vector<shared_ptr<CTest>> ct { make_shared<CTest>(10, 20), make_shared<CTest>(11, 21), make_shared<CTest>(12, 22), }; for (const auto c : ct) { // アクセスは*を介して行う(この場合は->) cout << c->foo << "," << c->bar << endl; } return 0; }
make_sharedはなんか注意点があるらしいですが、下記にまとまってる感じでした。
cflat-inc.hatenablog.com
shared_ptrとunique_ptrの使い分け
理由がなければ基本的にunique_ptrを使いましょう。
vectorの内部でポインタを保持したいときでstd::move
を使いたくない場合はshared_ptr
で良いかもしれません。まぁ、でもなるべくunique_ptr
を使いましょうってことで。
blog.ikappio.com
postd.cc
qiita.com
*1:参照は明示しないとダメ。どういうルールかは良く知らない