C ++中二维数组中的foreach循环
Posted
技术标签:
【中文标题】C ++中二维数组中的foreach循环【英文标题】:foreach loop in 2D Arrays in C++ 【发布时间】:2013-05-06 17:18:31 【问题描述】:我有一个 3x3 二维数组。我想触及它的所有元素。可能吗?我这样做:
int myArray[3][3];
for(int &i: myArray)
//MY CODE HERE.
但是当我这样做时,我得到了错误:
error: C2440: 'initializing' : cannot convert from 'int [3]' to 'int &'
我还在 Qt 5.0 x64 上使用 MSVC++ 2012 编译器。 如果可以的话,如何获取每个元素的索引号?
【问题讨论】:
【参考方案1】:如果您只想在一个循环中遍历所有元素,那么您可以执行以下操作 (C++11):
#include <type_traits>
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <cstdio>
#if defined(__clang__)
# define UTILITY_COMPILER_CXX_CLANG
# define UTILITY_COMPILER_CXX_VERSION __clang_major__
# define UTILITY_COMPILER_CXX_VERSION_MINOR __clang_minor__
# define UTILITY_COMPILER_CXX_VERSION_PATCHLEVEL __clang_patchlevel__
# if __clang_major__ < 3
# error unsuported clang version
# endif
#elif defined(__GNUC__)
# define UTILITY_COMPILER_CXX_GCC
# define UTILITY_COMPILER_CXX_VERSION __GNUC__
# define UTILITY_COMPILER_CXX_VERSION_MINOR __GNUC_MINOR__
# define UTILITY_COMPILER_CXX_VERSION_PATCHLEVEL __GNUC_PATCHLEVEL__
# if __GNUC__ < 4
# error unsuported gcc version
# endif
#elif defined(_MSC_VER)
# define UTILITY_COMPILER_CXX_MSC
# define UTILITY_COMPILER_CXX_VERSION _MSC_VER
#else
# error unknown compiler
#endif
#ifdef UTILITY_COMPILER_CXX_MSC
# if UTILITY_COMPILER_CXX_VERSION >= 1900
# define UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# endif
#else
# if __cplusplus >= 201103L
# ifdef UTILITY_COMPILER_CXX_GCC // specific case for GCC 4.7.x and lower
# if UTILITY_COMPILER_CXX_VERSION >= 5 || \
UTILITY_COMPILER_CXX_VERSION == 4 && UTILITY_COMPILER_CXX_VERSION_MINOR >= 8
# define UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# endif
# else
# define UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# endif
# endif
#endif
#ifdef UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# define CONSTEXPR constexpr
#else
# define CONSTEXPR
#endif
namespace utility
// bool identity / identities
template <bool b>
struct bool_identity
using type = bool;
static CONSTEXPR const bool value = b;
;
template <bool b>
CONSTEXPR const bool bool_identity<b>::value;
// Unrolled breakable `for_each` for multidimensional arrays
namespace detail
template<bool is_array>
struct _for_each_unroll
template <typename Functor, typename T, std::size_t N>
_for_each_unroll(_for_each_unroll * parent_, T (& arr)[N], Functor && f) :
parent(parent_), break_(false)
invoke(arr, std::forward<Functor>(f));
template <typename Functor, typename T, std::size_t N>
_for_each_unroll(_for_each_unroll * parent_, T (&& arr)[N], Functor && f) :
parent(parent_), break_(false)
invoke(std::forward<T[N]>(arr), std::forward<Functor>(f));
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I == N, void>::type
invoke(T (& arr)[N], Functor && f)
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I == N, void>::type
invoke(T (&& arr)[N], Functor && f)
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I < N, void>::type
invoke(T (& arr)[N], Functor && f)
if (!break_)
_for_each_unroll<std::is_array<T>::value> nested_for_each this, arr[I], std::forward<Functor>(f) ;
if (!nested_for_each.break_)
invoke<I + 1, Functor, T, N>(arr, std::forward<Functor>(f));
else if (parent) parent->break_ = true;
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I < N, void>::type
invoke(T (&& arr)[N], Functor && f)
if (!break_)
_for_each_unroll<std::is_array<T>::value> nested_for_each this, std::forward<T>(arr[I]), std::forward<Functor>(f) ;
if (!nested_for_each.break_)
invoke<I + 1, Functor, T, N>(arr, std::forward<Functor>(f));
else if (parent) parent->break_ = true;
_for_each_unroll * parent;
bool break_;
;
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, const T & value, Functor && f, bool_identity<false> is_breakable)
f(value);
;
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, const T & value, Functor && f, bool_identity<true> is_breakable)
if (!f(value))
this_.break_ = true;
;
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, T && value, Functor && f, bool_identity<false> is_breakable)
f(std::forward<T>(value));
;
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, T && value, Functor && f, bool_identity<true> is_breakable)
if (!f(std::forward<T>(value)))
this_.break_ = true;
;
template<>
struct _for_each_unroll<false>
template <typename Functor, typename T>
_for_each_unroll(void * parent, const T & value, Functor && f) :
break_(false)
_invoke_breakable(*this, value, std::forward<Functor>(f), bool_identity<!std::is_void<decltype(f(value))>::value>);
template <typename Functor, typename T>
_for_each_unroll(void * parent, T && value, Functor && f) :
break_(false)
_invoke_breakable(*this, value, std::forward<Functor>(f), bool_identity<!std::is_void<decltype(f(std::forward<T>(value)))>::value>);
bool break_;
;
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I == N, void>::type
for_each_unroll(T (& arr)[N], Functor && f)
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I == N, void>::type
for_each_unroll(T (&& arr)[N], Functor && f)
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I < N, void>::type
for_each_unroll(T (& arr)[N], Functor && f)
detail::_for_each_unroll<std::is_array<T>::value> nested_for_each nullptr, arr[I], std::forward<Functor>(f) ;
if (!nested_for_each.break_)
for_each_unroll<I + 1, Functor, T, N>(arr, std::forward<Functor>(f));
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I < N, void>::type
for_each_unroll(T (&& arr)[N], Functor && f)
detail::_for_each_unroll<std::is_array<T>::value> nested_for_each nullptr, std::forward<T>(arr[I]), std::forward<Functor>(f) ;
if (!nested_for_each.break_)
for_each_unroll<I + 1, Functor, T, N>(std::forward<T[N]>(arr), std::forward<Functor>(f));
int main()
int i = 0;
int a[2][3][4] = 0 ;
utility::for_each_unroll(a, [&](int & value)
value = i;
i++;
);
for (auto & j0 : a) for (auto & j1 : j0) for (auto & j2 : j1) printf("%u ", j2);
puts("\n");
i = 0;
int b[2][3][4] = 0 ;
utility::for_each_unroll(b, [&](int & value)
value = i;
i++;
if (i >= 3) return false;
return true;
);
for (auto & j0 : b) for (auto & j1 : j0) for (auto & j2 : j1) printf("%u ", j2);
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
https://godbolt.org/z/oEPf4GMsz
【讨论】:
【参考方案2】:在 C++ 中
using namespace std;
int main()
int a[3][3] = 1, 2, 3, 4, 5, 6, 7, 8, 9;
for (auto &i : a)
for (auto &j : i)
cout << j << " ";
cout << endl;
【讨论】:
作为说明,一般不要使用 using namespace std 或 cout ***.com/questions/1452721/…***.com/questions/213907/stdendl-vs-n【参考方案3】:只需输入int*
而不是int&
int myArray[3][3];
for(int* rows: myArray) // Iterating over rows
for(int* elem: rows)
// do some stuff
【讨论】:
这不会编译,也不会。 for ( : ) 不适用于 int*。【参考方案4】:只需使用auto
关键字
int myArray[3][3];
for(auto& rows: myArray) // Iterating over rows
for(auto& elem: rows)
// do some stuff
【讨论】:
不会把i
变成int*
吗?
@MohammadRezaHajianpour, auto
关键字是 C++11 的特性,是的(如基于范围的 for 循环)
@mwerschy,在这种情况下,rows
将被推导出为int (&)[3]
。
我在谈论你在编辑之前所做的事情;)虽然你当然是对的,它不会是int*
。以上是关于C ++中二维数组中的foreach循环的主要内容,如果未能解决你的问题,请参考以下文章