8

私の同僚のコードは次のようになりました。

void copy(std::string const& s, char *d) {
  for(int i = 0; i <= s.size(); i++, d++)
    *d = s[i];
}

s彼のアプリケーションがクラッシュします。条件が までしか行かないはずなので、範囲外のアクセスが原因だと思いますs.size() - 1

しかし、私の隣にいる他の人は、これが合法であることについて過去に議論があったと言います. 誰でも私のためにこれを片付けてもらえますか?

4

3 に答える 3

10

index で「要素」にアクセスするときに明確に定義された動作が*dあるかどうかという、質問が向けられているように見えるものとは何の関係もないため、無効である可能性を脇に置きましょう。std::string operator[]()std::string::size()

C++03 標準には、string::operator[]()(21.​​3.4 "basic_string要素アクセス")の次の説明があります。

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

戻り値: の場合pos < size()、 を返しますdata()[pos]。それ以外の場合pos == size()、const バージョンは を返しますcharT()。それ以外の場合、動作は未定義です。

sコード例ではであるためconst、動作は明確に定義されておりs[s.size()]、null 文字が返されます。ただし、sが でない場合const string、動作は未定義です。

constC++11は、このエッジ ケースで非 const バージョンとは非常に異なる動作をするバージョンのこの奇妙な動作を修正します。C++11 21.4.5「basic_string要素アクセス」は次のように述べています。

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

必要: pos <= size().

戻り値: *(begin() + pos) の場合pos < size()、それ以外の場合は、値を持つ T 型のオブジェクトへの参照charT()。参照値は変更されません。

stringしたがって、C++11 コンパイラの場合、 が であるかどうかにかかわらず、動作は明確に定義されていconstます。

質問とは関係ありませんが、C++11 が「参照された値を変更してはならない」と言っているのは少し奇妙だと思いますpos == size()s[i] = some_character;wheresが非 const であることstd:stringi < s.size(). その未定義の動作は今ですか?その条項は特殊なケースのcharT()オブジェクトにのみ適用されると思います。

もう 1 つの興味深い点は、どちらの標準も、 で返されるオブジェクトのアドレスが で返さs[s.size()]れるオブジェクトのアドレスに関連していることを要求していないように見えることですs[s.size() - 1]。つまり、返さcharT()れる参照が文字列データの末尾に連続している必要はないようです。これは、必要に応じてそのセンチネル要素の単一の静的コピーへの参照を返すだけの選択肢を実装者に与えるためだと思います (これは、C++ 11 の「変更してはならない」という制限についても説明します。場合)。

于 2012-05-13T09:46:19.117 に答える
7

cppreference は次のように述べています。

reference       operator[]( size_type pos );

const_reference operator[]( size_type pos ) const;

もしpos==size()

  • const バージョンは、値 CharT() (ヌル文字) を持つ文字への参照を返します。(C++11まで)
  • どちらのバージョンも、値 CharT() (ヌル文字) を持つ文字への参照を返します。非 const 参照を使用して null 文字を変更すると、未定義の動作が発生します。(C++11以降)

したがって、ヌル文字を変更しない限り問題ありません。

于 2012-05-13T09:08:35.120 に答える
0

そのようにしたい場合(同僚のコードも終端をコピーしようとします\0)、次のことができます

  • 使用してc_str()ください。
  • でループを使用し、後で手動でi < s.size()追加します。\0

編集:
まあ、他の答えから判断すると、Abyxのコメントが正しいと思うようになりました。配列dがオーバーフローしている可能性があります(または割り当てられていない可能性もあります)。最初にそれを確認してください。
ただし、a も必ずコピーしてください\0

于 2012-05-13T09:09:45.737 に答える