C++ 为什么std::set似乎强制使用常量迭代器?
考虑下面的简单程序,它尝试使用对集合中元素的非常量引用来迭代集合的值:C++ 为什么std::set似乎强制使用常量迭代器?,c++,c++11,stdset,C++,C++11,Stdset,考虑下面的简单程序,它尝试使用对集合中元素的非常量引用来迭代集合的值: #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_ <
#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;
}
是的,我知道我实际上并没有试图修改for循环中的元素。但问题是,我应该能够得到一个非常量引用来在循环中使用,因为集合本身不是常量限定的。如果我创建一个setter函数并在循环中使用它,我会得到同样的错误。一个集合就像一个没有值,只有键的映射。由于这些键用于加速集合上操作的树,因此它们不能更改。因此,所有元素都必须是常量,以防止底层树的约束被破坏。行为是通过设计实现的 给你一个非常量迭代器可以激发你改变集合中的元素;随后的迭代行为将是未定义的
< C++ >注意,C++标准称:“代码>集合:迭代器< /代码>是代码> const 。因此旧式的Pc++ 11方式仍然不能工作。 <代码>代码:STD::SET//COD>使用包含的值来形成快速数据结构(通常是红黑树)。更改值意味着需要更改整个结构。因此,强制
const
ness,std::set
可防止您将其推入不可用状态。来自:
在集合中,元素的值也标识它(值为
它本身是类型为T)的键,并且每个值必须是唯一的。价值
在容器中一次不能修改集合中元素的个数()
元素始终是常量,但可以从中插入或删除
集装箱
“不可用”,如“尝试使用时随机崩溃”。@Yakk更可能在某些操作中找不到元素,这可能更糟糕。我在这里详细解释了这一点:如果您确实想修改
std::set
的元素,可以使用const\u cast
。只需确保修改不会改变集合中元素的顺序,否则您将遇到未定义的行为。这是非常不安全的,这就是为什么你必须不厌其烦地去做。我明白了,但我可能在修改集合元素中的某个东西,它不会修改集合中的排序顺序;声明一个非常量集将从begin()返回一个非常量迭代器std::set无法知道这一点,因此它使所有const
都变得安全。如果您的结构具有可变数据和一些不可变的键字段,那么您可能应该使用一个映射,该映射的值为结构,键为不可变键字段的副本。如果你知道你没有改变值的顺序,你总是可以舍弃常数,但是我认为map方法更干净。根据whilebegin
确实返回了iterator
,iterator是const\u iterator
的别名,因为C++11我相信别名是用来实现通用容器接口的,所有容器都有iterator
和const\u iterator
。对于不知道std::set
的详细信息的模板,这可能会起作用,这是模板代码在任何地方都使用auto
的一个很好的理由,或者至少是为了限制它不打算修改的引用。如果提问者在其当前具有Int&
的位置使用Container::value\u type&
编写一些模板代码,那么该模板不必要地无法为集合实例化。
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) {
^