为什么std :: set似乎强制使用const_iterator?

ato*_*ate 34 c++ stdset c++11

考虑下面的简单程序,它尝试使用对其中元素的NON-const引用来遍历集合的值:

#include <set>
#include <iostream>

class Int
{
public:
   Int(int value) : value_(value) {}
   int value() const { return value_; }
   bool operator<(const Int& other) const { return value_ < other.value(); }
private:
   int value_;
};

int
main(int argc, char** argv) {
   std::set<Int> ints;
   ints.insert(10);
   for (Int& i : ints) {
      std::cout << i.value() << std::endl;
   }
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译时,我从gcc收到错误:

test.c: In function ‘int main(int, char**)’:
test.c:18:18: error: invalid initialization of reference of type ‘Int&’ from expression of type ‘const Int’  
for (Int& i : ints) {  
              ^  
Run Code Online (Sandbox Code Playgroud)

是的,我知道我实际上并没有尝试修改for循环中的元素.但重点是我应该能够在循环内部使用非const引用,因为set本身不是const限定的.如果我创建一个setter函数并在循环中使用它,我会得到相同的错误.

nat*_*ate 44

集合就像没有值的地图,只有键.由于这些键用于加速集合操作的树,因此它们无法更改.因此,所有元素必须是const,以防止底层树的约束被破坏.

  • std :: set无法知道,因此它使所有`const`都安全.如果您的结构具有可变数据和一些不可变关键字段,那么您可能应该使用带有结构作为值的映射,以及不可变键字段的副本作为键.如果你知道你没有改变值的排序,你总是可以const_cast远离const,但我认为map方法更清晰. (5认同)
  • 根据http://en.cppreference.com/w/cpp/container/set,而`begin`确实返回`iterator`,因为C++ 11,迭代器是`const_iterator`的别名 (5认同)
  • 我看到了,但我可能正在修改 set 元素中的某些内容,但不会修改其在 set 中的排序顺序;[http://www.cplusplus.com/reference/set/set/begin](http://www.cplusplus.com/reference/set/set/begin) 声称非常量集将返回一个非-来自 begin() 的 const 迭代器 (2认同)
  • 我相信别名是为了实现通用容器接口,其中所有容器都具有`iterator`和`const_iterator`.这可能会与不了解`std :: set`细节的模板发挥作用 (2认同)
  • 这是模板代码在任何地方使用`auto`的一个很好的理由,或者至少是const限定它不打算修改的引用.如果提问者在当前具有`Int&`的地方写了一些带有'Container :: value_type&`的模板代码,那么该模板将无法实例化一个集合. (2认同)

lis*_*rus 10

std::set使用包含的值来形成快速数据结构(通常是红黑树).更改值意味着需要更改整个结构.因此,强迫const,std::set阻止您将其推入不可用状态.

  • @Yakk更有可能在某些操作上找不到元素,这可能会更糟. (2认同)

Oha*_*tan 8

cpp参考:

在集合中,元素的值也标识它(值本身是类型T的键),并且每个值必须是唯一的.集合中元素的值不能在容器中修改一次(元素总是const),但可以在容器中插入或删除它们.


Fit*_*rcy 5

该行为是设计使然。

给您一个非常量迭代器可能会启发您更改集合中的元素。随后的迭代行为将是不确定的。

需要注意的是C ++标准说,set<T>::iteratorconst这样的老式前C ++ 11的方式仍然是行不通的。