通过迭代器分配给元素

Assigning to an element via iterator

本文关键字:元素 分配 迭代器      更新时间:2023-10-16

我认为我们可以通过其非常量迭代器为容器的优雅分配一个新值。所以我试了一下:

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

并失败了。我为什么失败?

根据标准 N4431 §23.2.4/6 关联容器 [associaciative.reqmts]强调我的):

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

std::set是一个关联容器,其值类型与键类型相同,因此,std::set<T>::iterator是一个常量迭代器。因此,你得到的失败是有充分理由的。

set实际上

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

有关更详细和细致的讨论,请参阅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;

11不能放在 std::set 容器的第一个迭代器位置,因为它违反了它的顺序。

所以很明显,我们不能使用迭代器取消引用std::set来更新元素。编译器不允许它,你会得到编译器错误。