4

私は次のコードを持っています - :

int main()
{
    set<string> s;
    s.insert( "asas" );
    s.insert( "abab" );

    for ( auto item : s )
    {
        cout << item << "\n";
        reverse( item.begin(), item.end() );
    }

    cout << "\n";

    for ( auto item : s )
    {
        cout << item << "\n";
    }
}

出力 -:

abab
asas

abab
asas

セットの要素は、関数によってまったく変更されていませんreverse()
セット内の要素はまったく変更できないと思います。しかし、これが事実である場合、そもそもなぜコンパイラ自体がエラーを出さないのでしょうか?

-std=c++14Windows 7 でフラグ付きの TDM-GCC 4.9.2 を使用しています。

4

3 に答える 3

10

a の要素はstd::setですconst。要素を変更したい場合は、コンテナを目的の状態にするために挿入と削除を行う必要があります。

あなたのコード例では:

for (auto item : s)

次のようなものに変換されます。

for (auto iter = s.begin(); iter != s.end(); ++iter)
{
    auto item = *iter; // Copy!
    // loop body
}

ループ誘導変数itemは、内の実際の要素への参照ではなく、からの要素のコピーです。その結果、は変更されません。セットを変更するには、や などのメンバー関数を呼び出す必要があります。setsetsetsetinserterase

に変更itemして&itemも、ここでは役に立ちません。これを行うと、セットの要素が const であるため、コンパイル時にエラーが発生し、reverseそれらに適用できなくなります。

于 2015-07-01T06:25:23.253 に答える
4

この範囲ベースのループは、セット内のすべての要素のコピーを作成します。

for ( auto item : s )

itemそのため、コンパイラ エラーを発生させずにループ内で変更できます。

コンテナーの要素を変更する場合は、参照が必要です。これを使用すると、セットの要素を変更できないため、実際にコンパイラ エラーが発生します。

for ( auto& item : s )
{
  // s is a set. You cannot modify item
于 2015-07-01T06:22:50.253 に答える