通过取消引用的迭代器访问 std::set
考虑:
#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
}
}
printsetofset1
与 printset(*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
编译并工作得很好。
为什么一个 printsetofset0
可以工作,而看似功能相同(且更短)的 preintsetofset1
却不起作用?
Consider:
#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
}
}
printsetofset1
with the printset(*siter);
gives error:
<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
See Godbolt Link here.
printsetofset0
with the lines: std::set<int> Set = *siter; printset(Set);
compiles and works just fine.
What is the reason why one printsetofset0
works, while seemingly functionally equivalent (and shorter) preintsetofset1
does not work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
迭代器指向的元素是常量。您可以在注释中阅读:因为iterator 和 const_iterator 是常量迭代器(实际上可能是相同的类型),不可能通过任何这些成员函数返回的迭代器来改变容器的元素。。但是,传递对
printset
函数的引用会违反此属性。在内部,集合允许通过索引结构进行快速访问。更改元素需要对集合重新排序(内部)。
您可以通过向
printset
函数的参数添加const
修饰符来解决这种情况:The elements, which the iterator points to, are constant. You can read it here in the Notes: Because both iterator and const_iterator are constant iterators (and may in fact be the same type), it is not possible to mutate the elements of the container through an iterator returned by any of these member functions.. But, passing a reference to your
printset
function would violate this property.Internally, sets allow fast access via index structures. Changing the elements would require to reorder the set (internally).
You can solve the situation by adding a
const
modifier to the parameter of yourprintset
function:所有打印函数都应该通过 const 引用获取参数,因为它们不需要修改参数。像这样:
我还建议使用基于范围的 for 循环来简化您的代码:
printset
无法采用非常量引用的原因是您将其传递给集合内的集合,并且集合中存储的值始终是 const。有关详细信息,请参阅:为什么std::set 似乎强制使用 const_iterator 吗?All your print functions should take their argument by const reference, because they don't need to modify the argument. Like this:
I also suggest a range-based for loop to simplify your code:
The reason
printset
cannot take a non-const reference is that you're passing it the set-within-a-set, and the values stored in sets are always const. For more on this, see: Why does std::set seem to force the use of a const_iterator?问题是,尽管集合类型同时定义了
iterator
和const_iterator
类型,但这两种类型的迭代器都为我们提供了读取-仅访问集合中的元素。也就是说,集合中的键是 const。我们可以使用集合迭代器来读取但不能写入元素的值。
因此,要解决程序中的错误,您需要向
printSet< 的名为
Set
的参数添加低级常量 /code> 功能如下图:Demo
The problem is that although the set types define both the
iterator
andconst_iterator
types, both types of iterators give us read-only access to the elements in the set. That is, the keys in a set areconst
. Wecan use a set iterator to read, but not write, an element’s value.
So to solve the error in your program you need to add a low-level const to the parameter named
Set
of theprintSet
function as shown below:Demo