【问题标题】:Erase-remove idiom with std::set failing with constness-related error [duplicate]带有 std::set 的擦除删除习语因 constness 相关错误而失败 [重复]
【发布时间】:2011-04-17 02:17:48
【问题描述】:

有人可以帮我吗?

编译这段代码:

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

【问题讨论】:

    标签: c++ stl set erase


    【解决方案1】:

    std::set 中,元素不可修改。因此,std::set::iterator 也是不可修改的。来自this 教程,第 27.3.2.1 节:

    在简单的关联容器中, 其中元素是键, 元素是完全不可变的;这 嵌套类型迭代器和 因此 const_iterator 是相同的。

    因此,erase-remove 成语不能按原样应用。您必须编写一个for 循环,并在其中使用成员函数std::set::erase。有关详细信息,请参阅此 question 和已接受的 answer 和另一个 answer,但简而言之,循环如下所示

    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;
        }
    }
    

    【讨论】:

      【解决方案2】:

      Erase-remove 惯用语不能与关联容器一起使用。关联容器不允许通过迭代器修改整个容器元素,这立即意味着不能对它们应用变异序列操作(如std::remove)。

      【讨论】:

        【解决方案3】:

        如前所述,您的代码不起作用,因为您尝试修改关联容器内的序列,但您不能这样做,因为该序列是不可变的。基本原理:set 包含一个有序序列,通常在二叉树中。如果你被允许修改它,你可能会破坏容器并且程序会崩溃。顺便说一句,在某些情况下它仍然可能发生。

        您可以将代码更改为:

        test.erase(30);
        

        或者使用 ArunSaha 的 (+1) 代码来获得更复杂的标准。

        【讨论】:

          【解决方案4】:

          如果我没记错的话,std::remove 永远不能与 std::set 元素一起使用。

          由于集合不是纯数组,因此您必须使用擦除。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-04-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多