66529


MFCでCArray::SetSize関数の使い方が分からず困っています。  
この関数の機能は、空または既存の配列のサイズを第一引数によって設定することは理解しましたが、  
必要に応じてメモリに割り当てるという、第二引数の部分が理解できませんでした。

参考にしたMSDNのサイト：  
<https://docs.microsoft.com/ja-jp/cpp/mfc/reference/carray-class?view=vs-2019>

第二引数のnGrowByは、サイズの増加が必要な場合に割り当てる要素スロットの最小数とありましたが、  
・サイズの増加とはどういう意味か？  
・サイズの増加が必要な場合とはどういう場合か？  
・割り当てる要素スロットとはどういう意味か？

が分かりませんでした。  
上記、教えて頂けるとありがたいです。  
どうかよろしくお願いいたします。


CC BY-SA 4.0
2020-05-12T04:26:46.600
66524
2020-05-12T05:21:34.180
21034
question
c++ mfc
MFCでCArray::SetSize関数の使い方が分からない


CArray::Add()をし続けると、いずれ内部に確保されたバッファがいっぱいになります。  
その状態でAdd()をすると、CArrayは内部バッファを拡張してから追加動作を行います。

さて、このとき、1要素分だけ拡張するのは頭の良い方法ではありません。  
なぜなら、次のAdd()で再度内部バッファを拡張しなければならないことが自明だからです。

では幾つ拡張するのが賢明でしょうか、これをある程度わかっているのは、CArrayを使用しているプログラマです。  
レドモンドの人たちはSetSize()の第二引数でこれを設定させることにしたというわけです。

ところで、nGrowByは省略可能な引数なので、特にこの値を設定する必要が無い場合は省略してよいです。省略するとどうなるのかは、コード見るのが早いですが、デバッガでもある程度わかります。Add()時にバッファのサイズを見ていると4個づつ増えているのが確認できるはずです。つまりデフォルトでは4がgrow
amountであるということですね。


CC BY-SA 4.0
2020-05-12T04:53:35.147
66526
2020-05-12T05:14:45.267
2020-05-12T05:14:45.267
3793
3793
66524
answer


前提知識として `CArray` (および標準 [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示")
の `std::vector` ) は

  * 連続したメモリ領域を使うことで要素のランダムアクセスを `O(1)` かつキャッシュヒット率大で可能とする
  * 連続したメモリ領域の末尾に未使用領域を事前に置くことで、そこまではコストなしで拡張できる
  * 拡張の際 **未使用領域がなくなったら** 全データを別の場所に複写するしかないのでとても遅い（これを再配置と呼ぶ）

という性質があります。

> ・サイズの増加とはどういう意味か？  
>  ・サイズの増加が必要な場合とはどういう場合か？

先の解説でいう再配置が生じるとき。

> ・割り当てる要素スロットとはどういう意味か？

あなたのプログラムが `CArray`
の拡張を随時行うロジックであるとき、再配置の後にも拡張を続ける可能性が高く、そうすると「再配置→拡張→再配置→拡張→再配置」が繰り返されることになり、とてつもなく遅くなります。頻繁な再配置を避けるには、十分余裕をもって再配置するとよいわけですが、その余裕分にどれだけの値を指定すると適切かは用途次第、つまりプログラマが自分で指定出来たほうが良いと
Microsoft のエンジニアは判断したようです。「割り当てる要素スロット」とはその余裕分で、それを第二引数の `nGrowBy`
で指定できるようになっています。 `nGrowBy` が

  * `-1` (や負数) のとき、現在のスロット増加分を変更しません
  * `0` のとき Microsoft の決めたロジックでスロットを増加させます  
(現実装では `4` または `m_nSize/8` または `1024`)

  * `正数` のとき、その個数分でスロットを増加させます


CC BY-SA 4.0
2020-05-12T05:21:34.180
66529
2020-05-12T05:21:34.180
8589
66524
answer