为啥 std::remove 需要 const 版本的迭代器? [复制]
Posted
技术标签:
【中文标题】为啥 std::remove 需要 const 版本的迭代器? [复制]【英文标题】:Why std::remove takes const version of iterators? [duplicate]为什么 std::remove 需要 const 版本的迭代器? [复制] 【发布时间】:2015-05-14 15:34:32 【问题描述】:我正在使用 Visual Studio 2013 编译非常简单的代码:
std::set<int> a 1, 2, 3 ;
std::remove(a.begin(), a.end(), 3);
我希望这不会出错,但我很惊讶。错误发出:
Error 1 error C3892: '_Next' : you cannot assign to a variable that is const c:\program files (x86)\microsoft visual studio 12.0\vc\include\algorithm
这怎么可能? a 是一个非常量 std::set。 std::remove() 移动它的元素,看起来完全合法。
在 VS 2008 中,以下类似代码编译时没有错误:
std::set<int> a;
std::remove(a.begin(), a.end(), 3);
【问题讨论】:
【参考方案1】:该集合是非常量的,但 set::begin()
、set::end()
返回一个 const_iterator。可以看到on cppreference。
我相信这是为了避免“局外人”能够交换元素,因为 set 的不变量之一是所有元素都已排序(这正是 std::remove
所做的,它移动元素以便您可以调用擦除之后,请参阅erase-remove idiom)
如果要删除元素,请使用erase 成员函数。
【讨论】:
是的,我注意到了这种行为。它与VS 2008不同。在VS 2008中,代码编译。 @Sheen 这是 C++ 标准本身的变化。 P.S.我不喜欢这种变化。您曾经能够制作带有关键部分的对象,只要您不更改密钥,您就可以根据需要修改对象的其余部分。不再允许这样做。 @MarkRansom - 有什么变化?我使用的所有编译器都拒绝std::remove(a.begin(), a.end(), 3)
,无论我告诉编译器编译的标准版本是什么。我怀疑这更像是 VS 2008(我不使用的编译器)不符合任何版本的标准。
@DavidHammen 我想我可能记错了。我所知道的是,我已经使用过几次这种模式,但很遗憾看到它消失了。【参考方案2】:
std::remove
适用于像 vector
和 list
这样的线性容器,而不是像 set
这样的排序容器。 (考虑一下:remove
交换元素。交换 set
的元素甚至 意味着是什么意思?)
听起来你想要std::set::erase
。
【讨论】:
以上是关于为啥 std::remove 需要 const 版本的迭代器? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
std::remove_if 将“const type”作为“this”参数传递会丢弃 linux 上的限定符 [重复]
std::remove 和 boost::filesystem::remove 之间的区别?