2010-07-27 93 views
5

也许这个问题是微不足道的,但想着这第二次我不知道该怎么做了以下真正的正确方法:迭代std :: vector(不带迭代器)时使用哪种类型?

std::vector<K> v = ...; 
for(T i=0; i<v.size(); ++i) { 
    const K& t = v[i]; 
    // use t *and i* 
} 

什么类型应该T是什么? int,unsigned int,int32_t,size_t(这将是v.size()的类型)还是其他建议?请尽量考虑可移植性,错误倾向性和性能,并在您的答案中保持客观。

编辑:我没有选择迭代器,因为它也想明确地使用索引号。

回答

6

i的类型应该与返回值size()相同,即std::vector<K>::size_type。但是,在实践中,size_t将会很好。如果你使用签名的整数类型,那么你的编译器可能会在小于比较中警告有符号/无符号不匹配。

通常你会使用迭代器这个反正:

std::vector<K> v = ...; 
for (std::vector<K>::iterator i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    // use t 
} 

或者C++ 0x中:

std::vector<K> v = ...; 
for (auto i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    // use t 
} 

在回答您关于使用迭代器向量索引评论,考虑向量迭代器的恒定时间操作的std::distance()函数:

std::vector<K> v = ...; 
for (auto i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    size_t index = std::distance(v.begin(), i); 
    // use t and index 
} 
+2

或者C++ 0x中:'为(自动I:V){...}'(N2930):-) – 2010-07-27 09:24:44

+1

现在我的问题是,什么更快/更清晰/可移植性:使用整数来迭代(并将其作为索引直接使用)或使用迭代器和距离函数来计算索引? – Danvil 2010-07-27 09:30:43

+0

@Danvil:最有可能的,没关系。两者都包含一个简单的增量和一个加法或减法。而在这两种情况下,这两种说法都不能进行同步。我期望分开增加i和迭代器的解决方案会稍微快一点,因为它可以被并行化。但是,我怀疑这种差异在实践中是可以衡量的。 – Sjoerd 2010-07-27 09:44:31

3

v.size返回的类型以及v[]预计的类型为std::vector<K>::size_type

但是,请考虑使用迭代器:出界的风险较低,您可以使用标准库算法。

3

类型T通常无关紧要,只要它与矢量大小一样大。

在性能方面,应该没有任何区别。

在错误倾向/便携性方面,我建议使用符号整数,因为如果你以某种方式减去i值,你会得到一个大的正数,这是很难检查不是负数。但由于v.size()size_t,如果使用T的一个符号整数,并v具有≥2 (或2 )项目,该i将有可能成为结束前无效。但是我认为,如果矢量需要大得多(特别是在64位平台上),那么还有其他更大的问题,而不是选择哪种类型的T。

从不使用int32_t作为计数器。


(这些都是之前OP的编辑:)

但在你的情况你可能想用一个迭代器迭代来代替。

for (std::vector<K>::const_iterator cit = v.begin(); cit != v.end(); ++ cit) { 
    const K& t = *cit; 
    // ... 
} 

随着Boost.Foreach你可以把这个烂摊子到

BOOST_FOREACH(const K& t, v) { 
    // ... 
} 

在C++ 0x中这将成为一个built-in feature(§ [stmt.ranged]),但据我所知没有编译器支持它尚未:

for (const K& t : v) { 
    // ... 
} 

但是大多数声称支持C++ 0x的编译器应该允许auto

for (auto cit = v.cbegin(); cit != v.cend(); ++ cit) { 
    const K& t = *cit; 
    // ... 
} 

或lambda表达式:

std::for_each(v.cbegin(), v.cend(), [](const K& t) { 
    ... 
}); 
+0

以及如何知道元素在这些案例中的位置?你是否认为迭代器和额外的计数比使用数字迭代更好? – Danvil 2010-07-27 09:28:24

+0

@Danvil:通常我会保留2个变量,计数器和迭代器。如果你想遍历非向量结构,这是必需的。但对于向量,'t = v [i]'和'i = distance(cit,begin)'具有相似的性能,并且都只涉及指针算术和位移。 – kennytm 2010-07-27 09:41:19

+0

如果我会使用int作为迭代器类型,考虑到事实,size()是size_t,通常是无符号的,比较signed和unsigned整数是不是慢一点?另外,编译器推导出这些恼人的警告之一,比较签名与无符号整数。 – Danvil 2010-07-27 09:45:58