6

最近、次のステートメントが当てはまらないことに気づきましたstd::string s

s.max_size() == s.get_allocator().max_size();

std::stringこれは興味深いと思います。デフォルトstd::allocator<char>では、理論上の制限がありsize_type(-1)ます(2の補数を想定していることはわかっていますが、実際の質問とは関係ありません)。実際の制限はこれよりも大幅に少なくなることを私は知っています。一般的な32ビットのx86システムでは、カーネルはアドレス空間の2GB(おそらく1GB)を占有し、実際の上限ははるかに小さくなります。

とにかく、GNU libstdc ++std::basic_string<>::max_size()は、使用しているアロケータが何を言っているかに関係なく、同じ値を返すように見えます(のようなもの1073741820)。

それで、疑問は残ります、なぜstd::basic_string<>::max_size()ただ戻ってこないのget_allocator().max_size()ですか?これが架空の上限であるように私には思えます。そして、割り当てが不足している場合は、をスローするだけなstd::bad_allocので、試してみませんか?

これは何よりも好奇心が強いのですが、少なくともこの1つの実装で2つが別々に定義されているのはなぜだろうと思っていました。

4

3 に答える 3

10

Microsoft Connectで、あなたの質問に関連するバグが投稿されました。マイクロソフトはそれに興味深い答えを持っています:

max_size()の意図された目的が何であるかを明確に説明していない標準の解釈に従って、設計によるものとして解決しました。アロケータmax_size()は、「X :: allocate()に有意義に渡すことができる最大値」(C ++ 03 20.1.5 [lib.allocator.requirements] /表32)として説明されていますが、コンテナーmax_size()は「可能な限り最大のコンテナのsize()」(23.1 [lib.container.requirements] /表65)として記述されます。コンテナmax_size()をアロケータmax_size()から派生させるかどうか、またはどのように派生させるかについては何も説明されていません。長年の実装では、コンテナmax_size()をアロケータmax_size()から直接派生させ、この値をオーバーフローチェックなどに使用してきました。あなたのような標準の他の解釈も可能ですが、私たちにとって明確に正しいわけではありません。規格の文言は、ここで明確にすることで確かに恩恵を受ける可能性があります。それが発生しない限り、2つの理由から、現在の実装を変更しないことにしました。(1)他の顧客が現在の動作に依存している可能性があり、(2)max_size()は基本的に何も購入しません。せいぜい、アロケータを消費するもの(コンテナなど)は、アロケータmax_size()を使用して、allocate()がいつ失敗するかを予測できますが、allocate()を呼び出すだけの方が良いテストです。これは、アロケータがメモリを提供するかどうかを決定するためです。コンテナを消費するものは、size()の大きさの保証としてcontainer max_size()を使用できますが、より簡単な保証はsize_typeの範囲です。2つの理由から、現在の実装を変更しないことにしました。(1)他の顧客が現在の動作に依存している可能性があり、(2)max_size()は基本的に何も購入しません。せいぜい、アロケータを消費するもの(コンテナなど)は、アロケータmax_size()を使用して、allocate()がいつ失敗するかを予測できますが、allocate()を呼び出すだけの方が良いテストです。これは、アロケータがメモリを提供するかどうかを決定するためです。コンテナを消費するものは、size()の大きさの保証としてcontainer max_size()を使用できますが、より簡単な保証はsize_typeの範囲です。2つの理由から、現在の実装を変更しないことにしました。(1)他の顧客が現在の動作に依存している可能性があり、(2)max_size()は基本的に何も購入しません。せいぜい、アロケータを消費するもの(コンテナなど)は、アロケータmax_size()を使用して、allocate()がいつ失敗するかを予測できますが、allocate()を呼び出すだけの方が良いテストです。これは、アロケータがメモリを提供するかどうかを決定するためです。コンテナを消費するものは、size()の大きさの保証としてcontainer max_size()を使用できますが、より簡単な保証はsize_typeの範囲です。アロケータを消費するもの(コンテナなど)は、allocator max_size()を使用して、allocate()がいつ失敗するかを予測できますが、allocate()を呼び出すだけで、メモリを割り当てるかどうかを決定するため、より適切なテストになります。コンテナを消費するものは、size()の大きさの保証としてcontainer max_size()を使用できますが、より簡単な保証はsize_typeの範囲です。アロケータを消費するもの(コンテナなど)は、allocator max_size()を使用して、allocate()がいつ失敗するかを予測できますが、allocate()を呼び出すだけで、メモリを割り当てるかどうかを決定するため、より適切なテストになります。コンテナを消費するものは、size()の大きさの保証としてcontainer max_size()を使用できますが、より簡単な保証はsize_typeの範囲です。

さらに、ここでコアイシュー#197を見つけることができます。委員会は、基準の文言を改善するための要求を検討しましたが、それは拒否されました。

それで、あなたの質問に対する答えは「なぜ..?」です。Standardは、max_size()の意図された目的が何であるかを明確に説明していないということです。

于 2009-10-20T06:48:03.130 に答える
4

私は完全にはわかりstd::basic_stringませんが、私が知る限り、文字列を連続メモリに格納するための現在の標準に制限されていません。たとえば、それをいくつかのチャンクに格納する場合があります。そのような各チャンクはに制限されstd::allocator::max_size()ますが、合計はそれより大きくなる可能性があります。

また、STLコンテナの場合もそうです。そして結局のところstd::basic_string、コンテナです。

于 2009-10-20T06:14:55.473 に答える
1

GCCの実装には、計算方法に関するコメントがありmax_size(文字列を使用して単一のブロックとして割り当てられている内部ハウスキーピングオブジェクトのサイズを減算する必要があります)、そのmax_size()4分の1を返すように追加します。根拠が与えられていないので、おそらくそれは単なる安全マージンですか?(ロープクラスも提供する必要があります。これは、おそらく非常に大きなストリングに使用されますか?)

VC ++を使用すると、ヌル文字の終了を説明するために、おそらくmax_size()1つ少ない値が返されます。allocator.max_size()

于 2009-10-20T07:02:49.057 に答える