古い質問だとは思いますが、誰もが見逃しているように思われることがいくつかあります。
最初は、これは2の乗算である:サイズ<< 1。これは乗算であるものINT(フロート(サイズ)* x)は、xは、*は小数点演算を数フローティングされ、プロセッサが有する:1と2の間floatとintの間でキャストするための追加の命令を実行します。言い換えると、マシンレベルでは、ダブリングは新しいサイズを見つけるために1つの非常に高速な命令を必要とします。1から2の間の何かを掛けるには、少なくともサイズをfloatにキャストする1つの命令、乗算する1つの命令(float乗算であるため、4倍または8倍ではないにしても、おそらく少なくとも2倍のサイクルが必要です)、およびintにキャストバックする1つの命令。これは、プラットフォームが特殊レジスターの使用を要求する代わりに、汎用レジスターで浮動小数点演算を実行できることを前提としています。つまり、各割り当ての計算には、単純な左シフトの少なくとも10倍の時間がかかると予想する必要があります。ただし、再割り当て中に大量のデータをコピーする場合は、それほど大きな違いはない可能性があります。
第二に、おそらく大きなキッカーです。誰もが、解放されているメモリがそれ自体に隣接しているだけでなく、新しく割り当てられたメモリにも隣接していると想定しているようです。すべてのメモリを自分で事前に割り当ててからプールとして使用しない限り、これはほぼ確実に当てはまりません。OSは時々最終的にはこれを実行しますが、ほとんどの場合、十分な空き領域の断片化が発生するため、適切なメモリ管理システムであれば、メモリがぴったり収まる小さな穴を見つけることができます。本当にビットチャンクに到達すると、連続したピースになってしまう可能性が高くなりますが、それまでに、割り当てが十分に大きくなり、それが問題になるほど頻繁に実行されなくなります。要するに、理想的な数を使用すると空きメモリスペースを最も効率的に使用できると想像するのは楽しいですが、実際には、プログラムがベアメタルで実行されていない限り(OSがない場合のように)それは起こりません。その下ですべての決定を行います)。
質問に対する私の答えは?いいえ、理想的な数はありません。これはアプリケーション固有であるため、実際に試す人は誰もいません。あなたの目標が理想的なメモリ使用量である場合、あなたはほとんど運が悪いです。パフォーマンスについては、割り当ての頻度が少ない方が良いですが、それだけで実行すると、4または8を掛けることができます。もちろん、Firefoxが1回のショットで1GBから8GBにジャンプすると、人々は文句を言うので、それは意味がありません。これが私が通り抜ける経験則です:
メモリ使用量を最適化できない場合でも、少なくともプロセッササイクルを無駄にしないでください。2を掛けると、浮動小数点演算よりも少なくとも1桁速くなります。大きな違いはないかもしれませんが、少なくともある程度の違いはあります(特に早い段階で、より頻繁でより小さな割り当ての間)。
考えすぎないでください。すでに行われていることを行う方法を理解するために4時間費やしただけの場合は、時間を無駄にしているだけです。正直なところ、* 2よりも優れたオプションがあったとしたら、それは数十年前にC ++ベクトルクラス(および他の多くの場所)で行われていたでしょう。
最後に、本当に最適化したい場合は、小さなものに汗を流さないでください。今日では、組み込みシステムで作業していない限り、4KBのメモリが無駄になることを気にする人は誰もいません。それぞれ1MBから10MBの間にある1GBのオブジェクトに到達した場合、2倍にするのは多分多すぎます(つまり、100から1,000オブジェクトの間です)。予想される膨張率を見積もることができれば、ある時点で線形成長率に平準化することができます。1分あたり約10個のオブジェクトが予想される場合は、1ステップあたり5〜10個のオブジェクトサイズ(30秒から1分に1回)で拡張することでおそらく問題ありません。
結局のところ、考えすぎないで、できることを最適化し、必要に応じてアプリケーション(およびプラットフォーム)に合わせてカスタマイズすることです。