回答編集履歴

2

質問者のコメントに対して説明を追記。

2021/05/30 22:51

投稿

ttact
ttact

スコア170

test CHANGED
@@ -11,3 +11,119 @@
11
11
 
12
12
 
13
13
  繰り返すと、要素数の制御を動的に行う必要があるかどうか、常にN個の要素が必要で増減しないかどうか、が使い分けのポイントではないかと思います。
14
+
15
+
16
+
17
+ ---
18
+
19
+ 5/31 コメントでの質問に対する回答
20
+
21
+
22
+
23
+ C++では、AがBを直接保持するケースでは、Aの変数が破棄されるとb_も破棄されることが保証されています(b_の破棄についてコードを書く必要はありません)。以下のケースでは、Aが破棄されたのにBが破棄されていないということは言語仕様上ありえません。
24
+
25
+ ```C++
26
+
27
+ class A
28
+
29
+ {
30
+
31
+ private:
32
+
33
+ B b_;
34
+
35
+ };
36
+
37
+ ```
38
+
39
+
40
+
41
+ newされたBを生ポインタで保持するケースでは、~A()にてb_を破棄する必要があります。これはなぜかというと、Aが管理しているのは、Bの実体ではなく、あくまで(Bの実体への)ポインタだからです。「AはBの実体を管理している」ということはC++文法上では何ら示されておらず、プログラマの頭の中にしかありません。このケースではdelete b_を書き忘れれば、Aが破棄されてもBが破棄されないということはありえます。
42
+
43
+ ```C++
44
+
45
+ class A
46
+
47
+ {
48
+
49
+ public:
50
+
51
+ ~A()
52
+
53
+ {
54
+
55
+ delete this->b_;
56
+
57
+ }
58
+
59
+
60
+
61
+ void create_b()
62
+
63
+ {
64
+
65
+ this->b_ = new B();
66
+
67
+ }
68
+
69
+
70
+
71
+ private:
72
+
73
+ B* b_;
74
+
75
+ };
76
+
77
+ ```
78
+
79
+
80
+
81
+ まともなC++プログラマであれば、生ポインタは使わずスマートポインタを使います。スマートポインタは、そのデストラクタで対象のオブジェクト(この場合Bの実体)のデストラクタを呼んでくれるので、~A()にて後始末のコードを記述する必要はなくなります。
82
+
83
+ ```C++
84
+
85
+ class A
86
+
87
+ {
88
+
89
+ public:
90
+
91
+ void create_b()
92
+
93
+ {
94
+
95
+ this->b_ = std::make_shared<B>();
96
+
97
+ }
98
+
99
+
100
+
101
+ private:
102
+
103
+ std::shared_ptr<B> b_;
104
+
105
+ };
106
+
107
+ ```
108
+
109
+
110
+
111
+ vectorは、保持している要素をきちんと破棄しています(gnuのvectorのソースコードを読むと大変勉強になると思います)。ただし以下のようにした場合は話は別です:
112
+
113
+ ```C++
114
+
115
+ std::vector<B*> a;
116
+
117
+ a.emplace_back(new B());
118
+
119
+ ```
120
+
121
+ 上記でaが保持しているのはBの実体ではなくポインタです。このようなケースではやはり自前でBの実体を破棄する必要があり、まともな(以下略)
122
+
123
+ ```C++
124
+
125
+ std::vector<std::shared_ptr<B>> a;
126
+
127
+ a.emplace_back(std::make_shared<B>());
128
+
129
+ ```

1

説明がこなれてない部分があったので修正。

2021/05/30 22:51

投稿

ttact
ttact

スコア170

test CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
 
8
8
 
9
- std::arrayとstd::vectorの違いは、「必ずN個の要素が生成される」かどうかだと思います。格納するオブジェクトのコンストラクタで何か処理を行ったりリソースを確保する場合、std::arrayずN回のコンストラクタ一気に実行されます。std::vectorはresize()を使えば同じようなことも実現できますし、そのあたりはプログラマが制御できます。
9
+ std::arrayとstd::vectorの違いは、「必ずN個の要素が生成される」かどうかだと思います。std::arrayでは必ずN個の要素が常に生成され存在する状態になりますし、そのためにN回のコンストラクタが一気に実行されます。なので格納するオブジェクトのコンストラクタで何か処理を行ったり、格納するオブジェクトがリソースを大きく消費する場合、それいいのかどうかを判断する出てきます。std::vectorはresize()を使えば同じようなことも実現できますし、そうでないようにも制御できます。
10
10
 
11
11
 
12
12