问题描述
我知道,我们可以通过这种方式遍历作为参数传递的数组:
//NO ERROR
void fun(int *a,int n){
for(int i=0; i<n; i++)
cout<<a[i];
}
但是,有没有什么办法可以在这样的函数中使用 for-each 循环遍历数组??
//ERROR
void fun(int *a,int n){
for(auto x:a)
cout<<x;
}
解决方法
在 C++20 中,您可以使用 std::span
:
#include <cstddef>
#include <cstdio>
#include <span>
void foo(int* arr,std::size_t sz) {
std::span<int> span{arr,sz};
for (int elm : span) {
std::printf("%d\n",elm);
}
}
或者您可以首先将 span
作为输入参数:
void foo(std::span<int> span) {
for (int elm : span) {
std::printf("%d\n",elm);
}
}
如果函数的签名是灵活的,我建议你使用第二个选项。
在 C++20 之前,here 是来自 GSL 的 span
的实现。或者使用 begin()
和 end()
函数创建自己的包装类。
指针不是数组。如果你将一个指向数组第一个元素的指针传递给一个函数,那么它就不再是一个数组,而是一个指针。
当您pass the array by reference时可以使用基于范围的循环:
#include <iostream>
template <size_t N>
void foo(int (&x)[N]) {
for (int i : x) std::cout << i << " ";
}
int main() {
int x[] = {1,2,3};
foo(x);
}
输出:
1 2 3
这是有效的,因为基于范围的循环使用 std::begin(x)
和 std::end(x)
来获取数组开头和结尾的迭代器。指针没有开始或结束。
替代非模板 C++20 解决方案:
auto range = std::views::counted(arr,sz);
for (auto elm : range) {
与 std::span
相比,这样做的好处是它更通用并且适用于任何迭代器,不需要像指针这样的连续迭代器。
使用 std::span
代替它的好处是您可以将 std::span
用作函数参数,而无需将其设为模板。
替代模板解决方案(适用于 C++20 之前):
template <class Range>
void foo(const Range& range) {
for (auto elm : range) {
与 int (&arr)[N]
相比,这样做的好处是它更通用。此模板适用于所有范围。
除了 range-for,您还可以考虑完全避免循环(在 C++20 之前有效):
auto print = [](auto elm) {
std::cout << elm;
}
std::for_each_n(arr,sz,print);
如果你没有 C++20,由于某种原因不能有 boost/ranges/GSL 库,并且没有模板,我推荐这个。
,是的,你可以。只需通过引用模板函数传递数组:
#include <iostream>
using namespace std;
template <size_t N> void foo(int (&arr)[N])
{
for (auto i:arr)
cout << i << " ";
}
int main()
{
int array[] = { 5,17,3452,546546,756756,75675,756753,345,53};
foo(array);
return 0;
}
,
和真正的答案:
int made[] = {10,15};
std::for_each(std::begin(made),std::end(made),[=](auto x){ std::cout << x << std::endl; });
您可以将 std::for_each
与 say std::execution::par
并行化。
带有函数代码的将
#include <iostream>
#include <vector>
#include <execution>
void f(int (&made)[3])
{
std::for_each(std::begin(made),[=](auto x){ std::cout << "and then " << x << std::endl; });
}
int main(int argc,char *argv[])
{
int made[] = {10,15};
f(made);
}