1. bluepost59

    Posted

    bluepost59
Changes in title
+unique_ptr
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,55 @@
+生ポインタをC++で使うのが不安で仕方ないのでスマートポインタを勉強しているのだが、unique_ptr周りの挙動で独特な部分があったのでまとめておこうと思う。
+
+#ポリモーフィックな定義をするとき
+C++でポリモーフィックなコードを書くときは、次のように親クラスのポインタに子クラスをnewで代入することが多い。
+
+```C++
+parent_class* myptr = new child_class;
+```
+
+ただし誰もが知るように大原則として**newしたら必ずdeleteしなければならない**ので、この方法ではうっかりdeleteし忘れる不安がついて回る。
+
+そこでポインタの代わりにスマートポインタを使う。これはC++11以降導入された機能で、スコープを抜けるとき勝手にデストラクタを呼んでくれる便利な代物だ。使うには```memory```ライブラリをincludeしておき、さらにコンパイルオプションに```-std=c++11```(c++11以降ならよい)と指定する必要がある。
+
+```C++
+std::unique_ptr<parent_class> myptr(new child_class);
+```
+
+このようにしておくことで、```myptr```がスコープを抜けて消滅するときデストラクタが呼ばれる。通常のポインタと同様まずはparent_classのデストラクタが呼ばれるし、それがvirtualならchild_class、parent_classの順でデストラクタが呼ばれる。
+
+#インスタンスの配列なら?
+Cを知ってる人ならわかるが、配列を指す生ポインタは配列の先頭アドレスを指す。そのため生ポインタでは次のようにすることでインスタンスの配列をアロケートすることができる。
+
+```c++
+parent_class* myptr = new child_class[10]
+
+//...
+
+//deleteするとき
+delete[] myptr
+```
+
+また、**組み込み型に限り**、スマートポインタでも同様に置き換えることができる。
+
+```c++
+std::unique_ptr<int[]> myint[10]
+```
+
+なので、インスタンスの配列でも同じようにしたくなるところだが、うまくいかない。
+
+```c++
+//コンパイルが通らない
+unique_ptr<parent_class[]> myptr(new child_class);
+unique_ptr<parent_class[]> myptr(new child_class[10]);
+//コンパイルは通るがresetできない
+unique_ptr<parent_class[]> myptr(child_class[10]);
+```
+
+そこで調べたところ、以下の記事にたどり着いた。
+
+https://ja.stackoverflow.com/questions/33196/unique-ptr%E9%85%8D%E5%88%97%E3%81%AB%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B%E6%96%B9%E6%B3%95
+
+どうやら**unique_ptrでインスタンスの配列の先頭アドレスを指すというような使い方はできない**ようで、無理にunique_ptrを使おうとしてもなかなか面倒なようだ。
+
+なのでこのような場合はおとなしく```vector<abs_class>```とするのがよいようだ。
+