1

Andrzejのmoveコンストラクターの記事へのコメントで、moved fromオブジェクトは、前提条件を持たない任意のメンバー関数を呼び出すことができると投稿しました。ベクトルが空でないという前提条件があるためstd::vector::front、moved-fromでは呼び出せない関数として例を示しました。std::vector、、およびを移動元で呼び出すことができる(ただし呼び出すべきではない)関数として、前提条件がないため、例を示しましたstd::vector::emptystd::vector::push_backstd::vector::reservestd::vector

しかし、それは私に考えさせられました。std::vector::push_backホストシステムで利用可能な十分な連続メモリがある必要があります。これは、std::vectorオブジェクトが実行されているシステムに関するものであるため、オブジェクトに対する要件ではありませんが、それでも私には前提条件のようです。

オブジェクトを有効であるが指定されていない状態のままにする移動コンストラクターのコンテキストは何ですか?それは、メモリ不足の可能性のある状況に適用されstd::vector::push_backますか?特に、std::vector::push_back移動前に機能していたとしたら、移動後に機能することが保証されていますか(他のプロセスがメモリを使い果たすなどの問題を無視して)?

参考:§17.6.3.1

Table 20 — MoveConstructible requirements [moveconstructible]
Expression  Post-condition
T u = rv;   u is equivalent to the value of rv before the construction
T(rv)       T(rv) is equivalent to the value of rv before the construction
rv’s state is unspecified [ Note:rv must still meet the requirements of the library compo-
nent that is using it. The operations listed in those requirements must work as specified
whether rv has been moved from or not. — end note ]
4

2 に答える 2

3

メモリが不足している場合はpush_back、例外を除いて終了しstd::bad_alloc、事後条件は適用されません。vectorオブジェクトは元の状態のままになります。

ベクトルが容量に達すると、次のようになります。

  1. より大きなブロックを割り当てます。これがbad_alloc例外をスローする場合は、それをユーザーに渡します。何も変更されていません。
  2. タイプが移動可​​能でない、または移動可能であるが、移動コンストラクターが例外をスローする可能性がある場合は、シーケンスの要素をより大きなブロックにコピーします。コンストラクターが例外をスローした場合は、大きなブロックに既にあるものをすべて破棄してから解放してから、例外を再スローします。
  3. タイプが移動可​​能で、移動コンストラクターがである場合はnoexcept、要素をより大きなブロックに移動します。これは成功する必要があります。仕様に違反している場合noexcept、実装は物事を元に戻そうとする必要はありません(これも失敗する可能性があります)。
  4. 元のメモリブロックを破棄し、新しいメモリブロックを保持します。

「有効だが指定されていない」は、この文脈ではそれ以上の意味はありません。ユーザーは、その中に何が含まれているのかを推測することは想定されていません。ただし、内容を確認するために検査するか、内容を無視してさらに追加することは問題ありません。

論理的には、オブジェクトは空のままにするか、元の状態のままにしておく必要があります。私はそれが実際には空のままにされるように指定されていることを思い出しているようですvector、そして多くのプログラマーはそうだと思います、正しいかどうか。

于 2013-01-05T07:37:17.187 に答える
2

オブジェクトを有効であるが指定されていない状態のままにする移動コンストラクターのコンテキストは何ですか?また、std :: vector :: push_backを使用した潜在的なメモリ不足の状況に適用されますか?

いいえ、適用されません。を実行するのに十分なメモリがあることpush_backは前提条件ではありません。システムにメモリがなくなったときに呼び出しても問題push_backありません(通常、プログラムは割り当てが成功するかどうかを事前に知ることはできません)。メモリが不足している場合は例外が発生します。push_backこれは、前提条件違反ではないという通常の動作です。

特に、std :: vector :: push_backが移動前に機能していた場合、移動後に機能することが保証されていますか(メモリを消費する他のプロセスなどの問題を無視します)?

試みることは合法ですpush_backが、動作することが保証されていません。移動後、ベクターのストレージが移動のターゲットに移動されたpush_back可能性があり、再割り当てが発生して失敗し、スローされる可能性がありbad_allocます。

しかし、割り当ての失敗を無視すると、push_backは成功します。ハワードのコメントにあるように、以前は要素の数が不明だったベクトルの数に1を加えた数が不明になります。有効ですが、あまり役に立ちません。

于 2013-01-06T14:55:00.750 に答える