我正在从Java转向C++,想知道C++中是否包含我在Java中使用的增强for循环,例如:
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
System.out.println("Count is: " + item);
}
在C++中是否存在类似的“快捷方式”?
我正在从Java转向C++,想知道C++中是否包含我在Java中使用的增强for循环,例如:
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
System.out.println("Count is: " + item);
}
在C++中是否存在类似的“快捷方式”?
C++11有一种叫做range-based for的方法。请记得要将类型标识为引用或者const引用。
对于C++03,可以使用BOOST_FOR_EACH或boost::bind与std::for_each结合使用来解决问题。使用Boost.Lambda还可以实现更多高级功能。如果你想让自己或同事感到沮丧,建议使用已被弃用的绑定器std::bind1st
和std::bind2nd
。
以下是一些示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/lambda/lambda.hpp>
#include <functional>
int main()
{
int i = 0;
std::vector<int> v;
std::generate_n(std::back_inserter(v), 10, [&]() {return i++;});
// range-based for
// keep it simple
for(auto a : v)
std::cout << a << " ";
std::cout << std::endl;
// lambda
// i don't like loops
std::for_each(v.begin(), v.end(), [](int x) {
std::cout << x << " ";
});
std::cout << std::endl;
// hardcore
// i know my lib
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// boost lambda
// this is what google came up with
// using for the placeholder, otherwise this looks weird
using namespace boost::lambda;
std::for_each(v.begin(), v.end(), std::cout << _1 << " ");
std::cout << std::endl;
// fold
// i want to be a haskell programmer
std::accumulate(v.begin(), v.end(), std::ref(std::cout),
[](std::ostream& o, int i) -> std::ostream& { return o << i << " "; });
return 0;
}
std::accumulate
可以这样使用。虽然我不会在我的代码中使用它,但我喜欢它在这里的用法。 - Nawazstd::vector<int> v;
// fill vector
for (const int& i : v) { std::cout << i << "\n"; }
它适用于C样式数组以及任何具有函数begin()
和end()
返回迭代器的类型。例如:
class test {
int* array;
size_t size;
public:
test(size_t n) : array(new int[n]), size(n)
{
for (int i = 0; i < n; i++) { array[i] = i; }
}
~test() { delete [] array; }
int* begin() { return array; }
int* end() { return array + size; }
};
int main()
{
test T(10);
for (auto& i : T) {
std::cout << i; // prints 0123456789
}
}
accumulate
的那种方法。 - pmr在C++03中不存在这样的可能性。然而新标准(C++11)具有此功能。请参见示例(摘自维基百科):
int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
x *= 2;
}
考虑使用std::vector<int>
而不是普通数组。这是C++对C数据类型的类比,使生活更加轻松。
int arr_len = sizeof(my_array) / sizeof(my_array[0]);
。 - Roman Byshko是和否。
1. 本地数组:不行,但你可以轻松找到大小
如果你有一个本地数组(int numbers[4] = {1, 2, 3, 4};
),那么你可以这样做size = sizeof(numbers) / sizeof(int)
。
2. 数组指针: 不行,你必须单独传递大小
如果你有一个数组指针(int* numbers = new int[4];
),除非你自己跟踪大小,否则无法确定大小。(或者对于c字符串的情况下是以null结尾的,但然后你必须迭代它,这是线性运行时间...)
请注意,我不认为数组指针是正确的术语,实际上你只是有指向数组第一个元素的指针,但已经分配了多个值的空间。不确定这被称为什么。也许只是一个指针?
3. STL容器:可以,你可以使用迭代器进行一些for循环魔法,或者通过获取大小使用索引
如果你有一个向量(std::vector<int> v(3, 0);),那么可以按以下方式迭代:
C++11:
auto it = v.begin();
for (auto it = v.begin(); it != v.end(); it++)
{
UseElement(*it);
}
或者显然(也适用于C++11,感谢jrok):
for (const int& i : v) { UseElement(i); }
C++ (pre-11):
->C++(11年前版本):
std::vector<int>::iterator it;
for (it = v.begin(); it != v.end(); it++)
{
UseElement(*it);
}
或者使用索引:
for (int i = 0; i < v.size(); i++)
{
UseElement(v[i]);
}
此外,您可以使用函数指针或functor与STL容器一起使用std算法的for_each(#include <algorithm>
),如下所示:
void foo(int i)
{
std::cout << i;
}
{
std::for_each(myvector.begin(), myvector.end(), foo);
}
MyType array[] = { ... }
for (MyType& x : array) {
...
}
&
进行声明。如果您不使用引用,则for循环将复制数组的每个元素到中(这可能是昂贵的操作)。MyType array[]
而不是 int MyType[]
。 - celtschk其他人已经提到这种循环风格是在C++11中添加的。然而,C++11更好:
for (auto const& item: numbers)
{
std::cout << "Count is: " << item << '\n';
}
这样,如果以后您将numbers
元素类型从int
更改为long
,甚至是您自己编写的bigint
类,则不需要对那个循环进行任何更改。
我发现这个简单的宏非常有用。我的绝大多数for
循环都涉及迭代STL容器:
#define For(it, container) for( typeof((container).begin()) it = (container).begin(); it != (container).end(); ++it)
vector<int> vector_of_ints;
... // initialize it somehow
For(integer, vector_of_ints) {
cout << *integer << endl;
}
有两件事情需要注意:首先,它是一个迭代器,因此您必须对其进行解引用。其次,For
的第二个参数将被评估多次。我尝试过其他方法,但最终还是回到这种简单的方法。