22

誰かがここで私を助けてくれますか?

このコードのコンパイル:

void test()
{
  std::set<int> test;
  test.insert(42);
  test.erase(std::remove(test.begin(), test.end(), 30), test.end());  // <- Line 33
}

コンパイル時に次のエラーが生成されます。

$ make
g++ -c -Wall -pedantic-errors -Wextra -Wunused -Werror a_star.cpp
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h: In function `_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = std::_Rb_tree_const_iterator<int>, _Tp = int]':
a_star.cpp:33:   instantiated from here
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:779: error: assignment of read-only location `__result.std::_Rb_tree_const_iterator<_Tp>::operator* [with _Tp = int]()'
make: *** [a_star.o] Error 1
4

4 に答える 4

27

ではstd::set、要素は修正できません。したがって、std::set::iteratorも変更できません。このチュートリアルのセクション 27.3.2.1から:

要素がキーである単純な連想コンテナーでは、要素は完全に不変です。したがって、ネストされた型 iterator と const_iterator は同じです。

したがって、erase-remove慣用句をそのまま適用することはできません。forループを作成し、そのstd::set::erase中でメンバー関数を使用する必要があります。正確な詳細については、この質問とこの受け入れられた回答と別の回答を参照してください。ただし、要するに、ループは次のようになります

typename std::set::iterator set_iter; 

for( set_iter it = s.begin(); it != s.end(); /* blank */ ) {
    if( some_condition() ) {
        s.erase( it++ );       // Note the subtlety here
    }
    else {
        ++it;
    }
}
于 2010-09-25T05:29:40.533 に答える
6

Erase-remove イディオムは、連想コンテナーでは使用できません。連想コンテナーでは、イテレーターを介してコンテナー要素全体を変更することはできません。つまり、変更シーケンス操作 ( などstd::remove) をそれらに適用することはできません。

于 2010-09-25T05:32:02.880 に答える
2

既に述べたように、連想コンテナー内のシーケンスを変更しようとするため、コードは機能しませんが、このシーケンスは不変であるため、これを行うことはできません。理論的根拠: set は、通常はバイナリ ツリーで順序付けられたシーケンスを保持します。変更を許可すると、コンテナーが破損し、プログラムがクラッシュする可能性があります。ところで、状況によってはまだ発生する可能性があります。

コードを次のように変更できます。

test.erase(30);

または、より複雑な基準には ArunSaha の (+1) コードを使用します。

于 2010-09-25T08:41:46.550 に答える
0

よく覚えていれば、std::remove を std::set 要素と一緒に使用することはありません。

セットは純粋な配列ではないため、消去を使用する必要があります。

于 2010-09-25T05:28:30.913 に答える