代码之家  ›  专栏  ›  技术社区  ›  Tryer

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

  •  -1
  • Tryer  · 技术社区  · 3 年前

    考虑:

    #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链接 here

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

    编译和工作都很好。

    为什么 打印集,共0个 有效,但功能上似乎相当(而且更短) preintsetofset1 不起作用?

    2 回复  |  直到 3 年前
        1
  •  3
  •   J.P.S.    3 年前

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

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

    您可以通过添加 const 的参数的修饰符 打印装置 功能:

    void printset(const std::set<int>& Set)
    
        2
  •  0
  •   John Zwinck    3 年前

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

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

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

    for (int val : Set)
    

    原因 printset 不能接受非常量引用,因为您正在将set-within-a-set传递给它,并且存储在集合中的值总是常量。有关此方面的详细信息,请参阅: Why does std::set seem to force the use of a const_iterator?

        3
  •  0
  •   user12002570    3 年前

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

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

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

    Demo