获取std::vector迭代器的更简便方法

Shorter way to get an iterator for a std::vector

本文关键字:方法 迭代器 std vector 获取      更新时间:2023-10-16

假设我有一个这样的向量

std::vector<a_complicated_whatever_identifier *> *something
    = new std::vector<a_complicated_whatever_identifier *>;
// by the way, is this the right way to do this?

现在我想为这个找到一个迭代器…所以我会这样做。

std::vector<a_complicated_whatever_identifier *>::iterator iter;

但是我发现它对我的代码来说有点太多了。我想知道,有没有更简单的方法来请求一个迭代器,而不管它的类型是什么?

我在想。

something::iterator iter;
    // OK, don’t laugh at me, I am still beginning with C++

好吧,它显然失败了,但我想你明白了。如何做到这一点或类似的事情?

你通常会给你的容器合理的类型,然后它是一件轻而易举的事:

typedef std::pair<int, Employee> EmployeeTag;
typedef std::map<Foo, EmployeeTag> SignInRecords;
for (SignInRecords::const_iterator it = clock_ins.begin(); ... )
           ^^^^^^^^^^^^^^^^^

通常,为容器设置一个方便的typedef比为迭代器设置一个显式的typedef更实用,也更具有自文档性(想象一下,如果您要更改容器)。

在新的c++(11)中,您可以使用auto it = clock_ins.cbegin()来获得一个常量迭代器

使用typedef。

typedef std::vector<complicated *>::iterator complicated_iter

然后像这样设置:

complicated_iter begin, end;

在c++ 11中,你将能够使用auto

auto iter = my_container.begin();

同时对vector使用typedef:

typedef std::vector<a_complicated_whatever_identifier *> my_vector;
my_vector::iterator iter = my_container.begin();

你应该很少有直接定义迭代器的需要。特别是,通过集合进行迭代通常应该由泛型算法完成。如果已经定义了一个可以完成这项工作的方法,那么最好使用它。如果没有,最好将自己的算法写成算法。在这种情况下,迭代器类型成为一个模板形参,使用您喜欢的任何名称(通常至少松散地引用迭代器类别):

template <class InputIterator>
void my_algorithm(InputIterator start, InputIterator stop) { 
    for (InputIterator p = start; p != stop; ++p) 
        do_something_with(*p);
}

既然它们已经被提到了,我将指出IMO, typedef和c++ 11的新auto(至少IMO)很少是这种情况的好答案。是的,它们可以消除(或至少减少)定义迭代器类型对象的冗长——但在这种情况下,它基本上只是治疗症状,而不是疾病。

作为题外话,我还要注意:

    指针向量通常是错误的。动态分配矢量更有可能是错误的。

至少现在,看起来好像您可能已经习惯了Java之类的东西,在Java中,总是必须使用new来创建对象。在c++中,这是相对不常见的——大多数时候,您只想定义一个局部对象,以便自动处理创建和销毁。

//顺便问一下,这是正确的方法吗?

你所做的是正确的。最好的方法取决于你想如何使用这个向量。

但是我发现它对我的代码来说有点太多了。我想知道,有没有更简单的方法来请求迭代器而不管类型是什么?

可以,可以将vector定义为类型:

typedef std::vector<a_complicated_whatever_identifier *> MyVector;
MyVector * vectPtr = new MyVector;
MyVector::iterator iter;

如果你有一个最新的编译器,我建议你试试c++11。大多数编译器以--std=c++0x标志的形式支持它。您可以做各种与类型推断相关的有趣的事情:

std::list<std::map<std::string, some_complex_type> > tables;
for (auto& table: tables)
{
     std::cout << table.size() << std::endl;
}
for (auto it = tables.begin(); it!= tables.end(); ++it)
{
     std::cout << it->size() << std::endl;
}

也看一下decltype和许多其他的便利:

// full copy is easy
auto clone = tables; 
// but you wanted same type, no data?
decltype(tables) empty;

将typedef与上面的组合的人为示例:

typedef decltype(tables) stables_t;
typedef stables_t::value_type::const_iterator ci_t;