将 const_iterator 分配给迭代器

Assigning a const_iterator to an iterator

我有以下代码片段(您可以在此处运行:http://coliru.stacked-crooked.com/a/2f62134b5c125051

#include <iostream>
#include <set>
#include <map>

int main() 
{
    std::set<std::pair<const int, const int>> const mySet{{0,0}}; // value_type = std::pair<const int, const int>
    for (std::set<std::pair<const int, const int>>::iterator it  = mySet.cbegin(); it != mySet.cend(); ++it)
    {
        std::cout<<"set it = " << it->first << " " << it->second << std::endl;
    }

    std::map<const int, const int> const myMap{{0,0}}; // value_type = std::pair<const int, const int>
    for (std::map<const int, const int>::iterator it  = myMap.cbegin(); it != myMap.cend(); ++it)
    {
        std::cout<<"map it = " << it->first << " " << it->second << std::endl;
    }   
}

有人可以解释一下为什么 std::set 下面没有抛出任何错误:

std::set<std::pair<const int, const int>>::iterator it  = mySet.cbegin();

而对于 std::map 下面抛出错误(没有从 _Rb_tree_const_iterator >_Rb_tree_iterator >) 如预期:

std::map<const int, const int>::iterator it  = myMap.cbegin();

它如何用于 std::set?将 const_iterator 分配给 迭代器 不应该总是抛出错误吗?

实际上 std::set<T>::iteratorstd::set<T>::const_iterator 相同,因为 std::set 的元素是不可变的。它没有可变迭代器类型。

std::map 情况并非如此,这就是您观察到不同行为的原因。

您不能修改集合元素。键必须是 const 以确保 set 承诺的不变量:元素已排序且唯一。 maps 元素也已排序,但您可以修改元素的映射值(键也是 const)。 std::map<A,B> 的元素是 std::pair<const A,B>.

cppreference 上,您可以看到 std::set 的迭代器的成员别名是

iterator Constant LegacyBidirectionalIterator

const_iterator Constant LegacyBidirectionalIterator

它们都是 const 迭代器。

另一方面 std::map 他们是:

iterator LegacyBidirectionalIterator

const_iterator Constant LegacyBidirectionalIterator

const_iterator 分配给 non-const 是错误的。这就像试图通过将指向 const 的指针分配给指向 non-const 的指针来强制转换 const 一样。它不会起作用,因为您不能使无法修改的东西变为可修改的。那会破坏 const-correctness.

来自 C++ 17 标准(26.2.6 关联容器)

6 iterator of an associative container is of the bidirectional iterator category. For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type.