我很抱歉这个模糊的标题,我真的不知道如何标题这个问题。
假设我有这个:
std::list<std::string> msgs;
for (std::list<std::string>::iterator it = msgs.begin(); it < msgs.end(); it++) {
// ...
}
对我来说,这很难读懂。 std::list<std::string>::iterator
几乎看起来像一个神奇的数字,特别是如果msgs
的声明很远,就像在头文件中一样。 IMO它会更容易阅读,如果是这样的话会更加语义化:
std::list<std::string> msgs;
for (msgs.iterator it = msgs.begin(); it < msgs.end(); it++) {
// ...
}
现在,这显然是非法的C ++。但我的问题是,有没有办法实现支持编写像这样的迭代器声明?
答案 0 :(得分:16)
如果你提供typedef,它会让生活变得更轻松:
typedef std::list<std::string>::iterator ListIterator;
for( ListIterator it = msgs.begin(); it != msgs.end(); ++it ){}
除此之外,c ++ 0x通过提供auto关键字为您完成:
for( auto it = msgs.begin(); it != msgs.end(); ++it ){}
编辑就像5年后的日期一样,但我更新了<
tp !=
并使用preincrement,因为这实际上是我多年来一直在做的事情,并且更有意义对我而言,它让我想知道我是怎么写这个答案而不是用那个
答案 1 :(得分:4)
有两种实用的规范方法:
typedef std::list<int> list_t;
list_t l;
// later:
for (list_t::iterator it = l.begin(), end = l.end(); it != end; ++it) {}
C ++ 0x-only auto
:
std::list<int> l;
// later:
for (auto it = l.begin(), end = l.end(); it != end; ++it) {}
此外,C ++ 0x允许:
std::list<int> l;
// later:
for (decltype(l)::iterator it = l.begin(), end = l.end(); it != end; ++it)
std::cout << *it << ", ";
我认为这是与特别提出的问题最接近的匹配(即使它不一定是最佳解决方案)。
缺点是将范围运算符(::
)应用于decltype
link 的能力最近才被投票到工作文件中,并且我还没有发现任何支持它的编译器(GCC 4.5.1 does not)。
答案 2 :(得分:1)
您可以使用typedef来清理它:
typedef std::list<std::string>::iterator string_iterator;
std::list<std::string> msgs;
for (string_iterator it = msgs.begin(); it != msgs.end(); it++) {
// ...
}
答案 3 :(得分:0)
所有容器都有这些typedef
,以便能够编写非常通用的代码。请考虑以下函数模板:
template<class T>
void foo(const T& container) {
for(T::const_iterator it = T.begin(); it != T.end(); it++) {
// do stuff
}
}
这使您可以编写可以使用定义类型const_iterator
和方法begin()
和end()
的任何对象的代码。
在C ++ 0x中,问题通过引入auto
关键字来解决:
for(auto it = container.begin(); it != container.end(); it++) {
// do stuff
}
答案 4 :(得分:0)
规范解决方案是
std::for_each(msgs.begin(), msgs.end(), ... );
在C ++ 0x之前,写...
位曾经有点困难(如果它有点复杂),但我们现在有lambda。