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

C++ class iterator utility: definition and usage

本文关键字:定义 用法 实用程序 迭代器 c++      更新时间:2023-10-16

我有一个名为A的类,在这个类中我有一个可迭代的容器,我按照一些访问规则——顺序、空性和其他规则对其进行迭代。

为了简化下面的例子,让我们假设我只是在遍历容器,但是这个不能用内置容器的迭代器来完成。
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. 为什么我必须使用typename时,我做:

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

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

    std::vector<int>::iterator it;
    

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

您不必使用typename。当您使用依赖的限定类型名称时,在模板中需要typename消歧器。这个关于StackOverflow的问答澄清了一些事情。:

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!
    }
};

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


2 -既然vector迭代器不需要typename标记,那么迭代器通常是如何定义的?

同样," vector迭代器不需要typename标记"也不是真的。如果您有该向量的显式专门化,例如:
std::vector<int>::iterator it; // "typename" not required

则不需要typename,因为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 -迭代器是在容器类内部定义的吗?——我猜它被命名为composition——或者,如果不是,它是如何将迭代器添加到类的命名空间中,如[..]

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

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!
    // ...
}

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

我很惊讶这竟然能起作用。'a'是一个变量,'a'是类。

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

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

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

好运