1. bluepost59

    No comment

    bluepost59
Changes in body
Source | HTML | Preview
@@ -1,55 +1,65 @@
生ポインタを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>```とするのがよいようだ。
+なのでこのような場合はおとなしく```vector<parent_class>```や```array<parent_class>```とするのがよいようだ。しかしこれではポリモーフィズムを実装できない。
+
+そこで、**unique_ptrのコンテナ**という形で定義する。arrayを使う場合は次のようになる。
+
+```
+std::array<std::unique_ptr<parent_class>, 10> myptrs;
+
+for(int i=0;i<10;i++){
+ myptrs[i].reset(new child_class);
+}
+```