C++ 通过迭代器分配给元素

C++ 通过迭代器分配给元素,c++,stl,C++,Stl,我认为我们可以通过容器的非常量迭代器为容器的元素赋值。所以我试着: #include<iostream> #include<set> typedef std::set<int>::iterator it; std::set<int> set_int; int main() { set_int.insert(1); it i = set_int.begin(); *i = 11; //error: assignmen

我认为我们可以通过容器的非常量迭代器为容器的元素赋值。所以我试着:

#include<iostream>
#include<set>

typedef std::set<int>::iterator it;

std::set<int> set_int;

int main()
{ 
    set_int.insert(1);
    it i = set_int.begin();
    *i = 11;  //error: assignment of read-only location
}
#包括
#包括
typedef std::set::迭代器;
std::set_int;
int main()
{ 
设置插入(1);
it i=set_int.begin();
*i=11;//错误:分配只读位置
}
结果失败了。为什么我失败了?

根据标准§23.2.4/6关联容器[Associative.reqmts](emphasis mine):

关联容器的迭代器属于双向迭代器类别对于值类型与键类型相同的关联容器,迭代器和常量迭代器都是常量迭代器。确实如此 未指定迭代器和常量迭代器是否为同一类型。[注意:
iterator
const\u迭代器
在这种情况下具有相同的语义,
iterator
可转换为
const\u迭代器
。用户可以通过在其函数参数列表中始终使用
const\u迭代器来避免违反一个定义规则。-结束说明]


std::set
是一个关联容器,其值类型与键类型相同,因此,
std::set::iterator
是一个常量迭代器。因此,您得到的失败是合理的。

一个
集合
实际上没有一个非
常量
迭代器,因为它的元素是不可变的。如果您考虑一下,假设您通过迭代器更改密钥。为什么可怜的集合会移动节点以保持树不变量等等


有关更详细、更细致的讨论,请参见Angelika Langer。

std::set
在内部保持元素的顺序。它基本上是一个红黑树二进制实现,并使用std::less作为默认的比较器。因此,如果我稍微修改一下您的示例,如下所示:

    typedef std::set<int>::iterator it;
    std::set<int> set_int;
    set_int.insert(1);
    set_int.insert(6); //I added 
    it i = set_int.begin(); //error: assignment of read-only location
    *i = 11;
typedef std::set::iterator it;
std::set_int;
设置插入(1);
设置插入(6)//我补充说
it i=set_int.begin()//错误:指定只读位置
*i=11;
11
不能放在std::set容器的第一个迭代器位置,因为它违反了它的顺序


因此很明显,我们不能使用
std::set
的迭代器解引用来更新元素。编译器不允许,您将得到编译器错误。

不知道该规则也适用于map、multiset、multimap,谢谢。