通过取消引用的迭代器访问 std::set

Accessing an std::set via a dereferenced iterator

考虑:

#include <stdio.h>
#include <set>

void printset(std::set<int>& Set) {
    for (std::set<int>::iterator siter = Set.begin(); siter != Set.end(); ++siter) {
        int val = *siter;
        printf("%d ", val);
    }
}

void printsetofset0(std::set<std::set<int>>& SetofSet) {
    for (std::set<std::set<int>>::iterator siter = SetofSet.begin(); siter != SetofSet.end(); ++siter) {
        std::set<int> Set = *siter;
        printset(Set);
    }
}

void printsetofset1(std::set<std::set<int>>& SetofSet) {
    for (std::set<std::set<int>>::iterator siter = SetofSet.begin(); siter != SetofSet.end(); ++siter) {
        printset(*siter);//this line gives error
    }
}   

printsetofset1printset(*siter); 给出错误:

<source>: In function 'void printsetofset1(std::set<std::set<int> >&)':
<source>:20:34: error: binding reference of type 'std::set<int>&' to 'const std::set<int>' discards qualifiers
   20 |                         printset(*siter);
      |                                  ^~~~~~
<source>:4:38: note:   initializing argument 1 of 'void printset(std::set<int>&)'
    4 |         void printset(std::set<int>& Set) {
      |                       ~~~~~~~~~~~~~~~^~~
Compiler returned: 1

见神马 Link here.

printsetofset0 行:std::set<int> Set = *siter; printset(Set);

编译和工作正常。

为什么一个 printsetofset0 有效,而看似功能相同(且更短)的 preintsetofset1 却无效?

你所有的打印函数都应该通过 const 引用来获取它们的参数,因为它们不需要修改参数。像这样:

void printset(const std::set<int>& Set)

我还建议使用 range-based for 循环来简化您的代码:

for (int val : Set)

printset 不能采用 non-const 引用的原因是您将其传递给 set-within-a-set,并且存储在集合中的值始终是常量。有关更多信息,请参阅:

迭代器指向的元素是常量。您可以在 Notes 中阅读它: 因为迭代器和 const_iterator 都是常量迭代器(实际上可能是同一类型),所以不可能改变其中的元素通过由这些成员函数中的任何一个返回的迭代器访问容器。。但是,传递对 printset 函数的引用会违反此 属性.

在内部,集合允许通过索引结构进行快速访问。更改元素需要重新排序集合(内部)。

您可以通过在 printset 函数的参数中添加 const 修饰符来解决此问题:

void printset(const std::set<int>& Set)

问题是尽管集合类型同时定义了iteratorconst_iterator类型,但两种类型的迭代器都给了我们 read-only 访问 集合中的元素。也就是说,一个集合中的键是const。我们 可以使用集合迭代器读取但不能写入元素的值。

所以要解决你程序中的错误你需要添加一个low-level const到参数[= printSet函数的14=]如下图:

//------------vvvvv--------------------------->low-level const added here
void printset(const std::set<int>& Set) {
        //other code as before
    }

Demo