-3

次の簡単なコードを見てください。

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s("1234567890");
    string::iterator i1 = s.begin();
    string::iterator i2 = s.begin();
    string s1, s2;
    s1.append(i1, ++i1);
    s2.append(++i2, s.end());

    cout << s1 << endl;
    cout << s2 << endl;
}

出力はどうなると思いますか?

あなたは、私のように、それが次のようになることを期待しますか?

1
234567890

違う!それは:

234567890

つまり、最初の文字列は空です。

インクリメント演算子をプレフィックスとする継ぎ目は、イテレータで問題があります。または私は何かを逃していますか?

4

4 に答える 4

14

何かが足りません。これは実際にはイテレータとは何の関係もありません。関数への引数が評価される順序は指定されていません。そのためappend(i1, ++i1);、のタイプに関係なく、:は不特定の動作に依存しますi1。たとえば、次のようなもっと単純なものを考えます。

void print(int a, int b) { 
    std::cout << a << " " << b << "\n";
}

int main() { 
    int a =0;
    print(a, ++a);
    return 0;
}

出力は、完全に合理的に期待できる「0 1」である可能性がありますが、完全に合理的に「11」である可能性もあります。これは指定されていないため、コンパイラのバージョンごとに変更される可能性があります。また、フラグを変更するときに同じコンパイラを使用する場合でも、(理論的には)月の満ち欠けによって異なる可能性があります...

于 2010-02-09T17:46:01.063 に答える
8

C ++実装は、引数を任意の順序で自由に評価できます。この場合、++ i1が最初に評価されると、空の文字列が取得されます。

于 2010-02-09T17:41:27.730 に答える
3

C ++標準では、関数の引数が評価される順序については何も指定されていないため、実装に依存します。C ++では、関数に入る前に関数への引数を完全に評価する(およびすべての副作用を投稿する)必要がありますが、実装では引数を任意の順序で自由に評価できます。

あなたの場合i++、両方のパラメータを同じにする前に評価され、空の文字列になります。

この動作の詳細については、comp.compilersニュースグループをご覧ください。

于 2010-02-09T17:43:11.233 に答える
3

バグではありません。

の引数の順序

s1.append(i1, ++i1);

評価されるのは規格で指定されていません。コンパイラーは、選択した任意の順序を自由に使用できます。この場合、++i1最初の()の前に2番目の引数()を評価し、i1コピーするnull範囲を指定します。

于 2010-02-09T17:43:31.353 に答える