_std::string::operator[]
_が境界チェックを行わないことを何度も見てきました。 string :: atとstring :: operator []? の違いは何ですか?2013年に尋ねられた回答によると、_operator[]
_は境界チェックを行いません。
これに関する私の問題は、[string.access]の標準(この場合は ドラフトN3797 )を見ると、
_const_reference operator[](size_type pos) const; reference operator[](size_type pos);
_
- 必要なもの:
pos <= size()
。- 戻り値:
*(begin() + pos)
ifpos < size()
。それ以外の場合は、値charT()
のタイプcharT
のオブジェクトへの参照を返します。オブジェクトを変更すると、未定義の動作が発生します。- スロー:何もありません。
- 複雑さ:一定時間。
これにより、_operator[]
_は、文字列の要素を返す必要があるのか、デフォルトのcharT
を返す必要があるのかを判断するために、何らかの境界チェックを行う必要があると思います。この仮定は正しく、境界チェックを行うには_operator[]
_が必要になりましたか?
言葉遣いは少し紛らわしいですが、詳細に調べると、実際には非常に正確であることがわかります。
それはこれを言います:
[]
_の引数が=nであるか、<n。charT()
(つまり、ヌル文字)を取得します。ただし、前提条件を破った場合のルールは定義されておらず、=nのチェックは暗黙的に満たすことができます(ただし、明示的には満たされません) charT()
を実際に位置nに格納することにより、強制されます。
したがって、実装は境界チェックを実行する必要はありません…そして一般的なものは実行しません。
_
operator[]
_は、ある種の境界チェックを行って決定しました...
いいえ、そうではありません。前提条件付き
必要なもの:pos <= size()。
[〜#〜]仮定[〜#〜]常に文字列の要素を返すことができると仮定できます。この条件が満たされない場合:未定義の動作。
_operator[]
_は、文字列の先頭からposだけポインタをインクリメントする可能性があります。文字列が短い場合は、文字列の背後にあるデータへの参照が返されます。単純なC配列の古典的な範囲外のように。
pos == size()
の場合を完全にするために、内部文字列データの最後に追加のcharT
を割り当てることができます。したがって、チェックなしでポインタをインクリメントするだけでも、指定された動作が提供されます。
まず、requires句があります。 require句に違反すると、プログラムは未定義の方法で動作します。それはpos <= size()
です。
したがって、言語はその場合に何が起こるかを定義するだけです。
次の段落では、pos < size()
の場合、文字列内の要素への参照を返すと述べています。また、pos == size()
の場合、値charT()
でデフォルトで作成されたcharT
への参照を返します。
これは境界チェックのように見えるかもしれませんが、実際に起こることは、_std::basic_string
_が要求よりも1つ大きいバッファを割り当て、最後のエントリにcharT()
を入力することです。次に、_[]
_は単にポインタ演算を行います。
私はその実装を回避する方法を考え出そうとしました。規格はそれを義務付けていませんが、私は自分自身に代替案が存在することを納得させることができませんでした。 .data()
には、単一のバッファーを回避するのが難しい厄介な問題がありました。
この標準コンテナの演算子は、通常の配列の演算子[]の動作をエミュレートします。したがって、チェックは行いません。ただし、デバッグモードでは、対応するライブラリがこのチェックを提供できます。
インデックスを確認したい場合は、代わりにメンバー関数at()
を使用してください。
http://en.cppreference.com/w/cpp/string/basic_string/operator_at
指定された位置posにある文字への参照を返します。 境界チェックは実行されません。
(エンファシスマイン)。
境界チェックが必要な場合は、 std :: basic_string :: at を使用します。
この標準は、チェックされていない配列アクセスが行うことを基本的に説明しているため、実装が境界チェックを提供する必要があることを意味します。
範囲内でアクセスする場合、それは定義されています。外に出ると、未定義の動作がトリガーされます。