std::for_each可以在范围内"迭代",所以如果要将其与长度不确定的数组一起使用,则需要使用自定义迭代器来指示数组的结尾(即NULL成员)。如果您坚持使用以NULL结尾的char*数组,当然可以为其创建自己的for_each函数,例如如下:
template <typename Function>
void for_each_in_null_terminated_cstring_array(const char** array, Function f)
{
while (*array) {
f(*array);
array++;
}
}
const char *names[] = { "Bob", "Adam", "Simon", NULL };
for_each_in_null_terminated_cstring_array(names, func);
我并不是真正推荐这种解决方案。
编辑:是的,更通用总是更好的,不是吗?
template <typename T, typename Function>
void for_each_in_null_terminated_array(T* array, Function f)
{
while (*array) {
f(*array);
array++;
}
}
(这是我之前提到的以空字符(“false”)结尾的迭代器的实现 - 根据下面的建议进行了一些更改。它应该是一个真正的InputIterator)
template <class T>
class nt_iterator: public std::iterator<std::input_iterator_tag, T>
{
public:
typedef typename nt_iterator<T>::pointer pointer;
typedef typename nt_iterator<T>::value_type value_type;
nt_iterator(): p(), pte(true) {}
nt_iterator(pointer p_): p(p_), pte(!p_) {}
nt_iterator(const nt_iterator<T>& rhs): p(rhs.p), pte(rhs.pte) {}
nt_iterator<T>& operator++() {
++p;
if (!*p) pte = true;
return *this;
}
nt_iterator<T> operator++(int) {
nt_iterator n(*this);
operator++();
return n;
}
bool operator==(const nt_iterator<T>& rhs) {
return pte && rhs.pte || p == rhs.p;
}
bool operator!=(const nt_iterator<T>& rhs) {
return !(operator==(rhs));
}
value_type operator*() { return *p; }
private:
pointer p;
bool pte;
};
以及它的使用方式:
void print(const char* str);
int main()
{
const char* array[] = {"One", "Two", "Three", NULL, "Will you see this?"};
std::for_each(nt_iterator<const char*>(array),
nt_iterator<const char*>(),
print);
}
使用std::for_each
可能会比循环版本慢一点,因为需要增加等价性检查的数量。当然,与例如打印文本相比,速度差异微不足道,但应注意std::for_each
并不能神奇地使循环更快(实际上,如果您期望过高,您可能会惊讶地看到编译器供应商如何定义该函数)。
std::list<std::string>
(如果更适合则使用std::vector
)表示。这将一次性解决您所有的问题。 - Björn Pollex