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

C++类迭代器实用程序:定义和用法

  •  2
  • Rubens  · 技术社区  · 11 年前

    我有一个名为 A ,在这个类中,我有一个可迭代的容器,我会按照一些访问规则(order、empty和其他规则)对其进行迭代。

    为了简化下面的例子,让我们考虑一下我只是在遍历容器,但是 不能 使用 内置容器的迭代器 .

    class A {
    public:
        class iterator {
        public:
            // Constructor
            iterator() {
            }
            // Destructor
            ~iterator() {
            }
            // Advances the iterator
            void operator++() {
               // Some accessing policy
            }
        };
    private:
        std::vector<int> a;
    };
    

    除了当我声明迭代器时,我必须使用 typename --我几乎认为这是用来告诉编译器我所拥有的是一个类型,而不是类本身。

    问题:

    1. 为什么我必须使用 类别名 当我这样做时:

      A a;
      for (typename A::iterator it(...); it != ...; ++it) {
      }
      
    2. 迭代器通常是如何定义的,因为向量迭代器不需要 类别名 标签它是否必须从类定义中声明向量,而不是从向量本身声明?

      std::vector<int> v;
      for (std::vector<int>::iterator it(v.begin()); it != v.end(); ++it) {
      }
      
    3. 迭代器是在容器类中定义的吗?我猜它是命名的composition,或者,如果不是,迭代器如何添加到类的命名空间中,如:

      std::vector<int>::iterator it;
      
    2 回复  |  直到 11 年前
        1
  •  4
  •   Community Egal    7 年前

    1-为什么我必须使用 typename 当我这样做时:[…]

    您不必使用 类别名 这个 类别名 需要消歧器 在…内 当您使用依赖的限定类型名称时,模板。 This Q&A on StackOverflow clarifies things 。这个:

    A a;
    typename a::iterator it; // ERROR!
    

    不合法的 C++前提是 A 不是模板参数的名称,您应该只执行以下操作:

    A::iterator it;
    

    如果您在一个模板内,并且 A. 是模板参数的名称,例如:

    template<typename A>
    struct X
    {
        void foo()
        {
            typename A::iterator it;
        //  ^^^^^^^^
        //  This is necessary here!
        }
    };
    

    那么你必须使用 类别名 告诉编译器 :: 是类型的名称。


    2-迭代器通常是如何定义的,因为向量迭代器不需要 类别名 标签

    同样,“ 矢量迭代器不需要 类别名 标签 “.如果您对该向量有明确的专门化,例如:

    std::vector<int>::iterator it; // "typename" not required
    

    然后 类别名 不需要,因为在中不需要 A::iterator it 。但是,如果您处于以下情况下的模板内部,则需要该模板:

    template<typename A>
    struct X
    {
        void foo()
        {
            typename std::vector<A>::iterator it;
        //  ^^^^^^^^
        //  This is necessary here!
        }
    };
    

    那是因为 std::vector<A>::iterator 这是一个限定的、依赖的类型名称。


    3-迭代器是在容器类中定义的吗?我猜它是命名合成的。如果不是,迭代器如何添加到类的命名空间中,如[..]

    这可以通过定义嵌套类来实现,也可以简单地通过使用类型别名来实现:

    template<typename T>
    struct X
    {
        typedef T* iterator;
        iterator begin() { /* ... */ }
        // ...
    };
    
    X<int>::iterator it; // OK: "typename" not required
    
    template<typename T>
    void foo(X<T>& x)
    {
        typename X<T>::iterator it = x.begin();
    //  ^^^^^^^^
    //  This is necessary here!
    
        // ...
    }
    
        2
  •  1
  •   Community Egal    7 年前

    您的示例代码有很多问题,所以这可能是您正在寻找的答案( 挥手 ):)当然,如果你的例子不正确,那么所有的赌注都会落空。

    我很惊讶这会奏效。”“a”是一个变量,“a”是类。

    此外,当使用默认构造函数声明变量时,不使用结束括号()。

    A a;
    A::iterator it;
    for (A::iterator it; it != ...; ++it) {
    }
    

    此外,迭代器是在容器类中定义的。只有在处理模板时,并且只有在访问可以被解释为静态成员或函数/嵌套类或typedef的东西时,才需要使用typename。答案可以进一步解释这一点 here 这也是Andy Prowl给的。

    祝你好运