28

std::string::operator[]境界チェックを行わないものを何度も見てきました。string ::at と string::operator[] の違いは何ですか? operator[]、2013年に尋ねられた、答えはそれが境界チェックをしないと言います。

これに関する私の問題は、[string.access]の標準 (この場合はドラフト N3797 ) を見る場合です。

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
  1. 必要: pos <= size() .
  2. 戻り値: *(begin() + pos)の場合pos < size()charTそれ以外の場合は、 value を持つ型のオブジェクトへの参照を返しますcharT()。オブジェクトを変更すると、未定義の動作が発生します。
  3. スロー:なし。
  4. 複雑さ:一定時間。

これによりoperator[]、 string または default の要素を返す必要があるかどうかを判断するために、何らかの境界チェックを行う必要があると思いますcharT。この仮定は正しく、operator[]境界チェックを行う必要がありますか?

4

5 に答える 5

14

operator[]判断するために何らかの境界チェックを行いました...

いいえ、そうではありません。という前提で

必須: pos <= size()。

常に文字列の要素を返すことができると仮定することができます。この条件が満たされない場合: 未定義の動作。

operator[]おそらく、ポインタを文字列の先頭から pos ずつインクリメントするだけです。文字列が短い場合は、それが何であれ、文字列の背後にあるデータへの参照を返すだけです。単純な C 配列の古典的な範囲外のように。

内部文字列データの最後にpos == size()エクストラを割り当てた可能性がある場合を完全にするため。charTしたがって、チェックなしでポインタをインクリメントするだけでも、規定の動作が実現します。

于 2016-07-21T14:09:58.443 に答える
4

まず、require 句があります。requires 句に違反すると、プログラムは未定義の方法で動作します。それはpos <= size()です。

したがって、言語はその場合に何が起こるかを定義するだけです。

pos < size()次の段落では、 の場合、文字列内の要素への参照を返すと述べています。に対しては、 valuepos == size()で構築されたデフォルトへの参照を返します。charTcharT()

これは境界チェックのように見えるかもしれませんが、実際には、std::basic_string要求されたものよりも 1 つ大きいバッファを が割り当て、最後のエントリにcharT(). 次に[]、単純にポインター演算を行います。

私はその実装を回避する方法を考え出そうとしました。標準では義務付けられていませんが、代替案が存在することを確信できませんでした。.data()単一のバッファーを回避するのが難しくなるという厄介なことがありました。

于 2016-07-21T14:20:14.053 に答える
2

標準コンテナーのこの演算子は、通常の配列の演算子 [] の動作をエミュレートします。したがって、チェックは行われません。ただし、デバッグ モードでは、対応するライブラリがこのチェックを提供できます。

インデックスを確認したい場合は、at()代わりにメンバー関数を使用してください。

于 2016-07-21T14:09:31.490 に答える