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



考虑:

#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

请参阅此处的Godbolt链接。

printsetofset0与线路:std::set<int> Set = *siter; printset(Set);

编译和工作都很好。

为什么一个printsetofset0工作,而看似功能等效(更短(的preintsetofset1不工作?

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

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

您可以通过在printset函数的参数中添加const修饰符来解决这种情况:

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

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

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

我还建议使用基于范围的for循环来简化代码:

for (int val : Set)

printset不能接受非常量引用的原因是,您正在将set-within-a-set传递给它,并且存储在集合中的值总是常量。有关更多信息,请参阅:为什么std::set似乎强制使用const_iterator?

问题是,尽管集合类型定义了iteratorconst_iterator类型,但这两种类型的迭代器都为我们提供了对集合中元素的只读访问。也就是说,一个集合中的密钥是const。我们可以使用集合迭代器读取但不能写入元素的值。

因此,要解决程序中的错误,您需要在printSet函数的名为Set的参数中添加低级常量,如下所示:

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

演示

最新更新