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&amp;

    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 (&amp;)[3] 我在谈论你在编辑之前所做的事情;)虽然你当然是对的,它不会是int*

以上是关于C ++中二维数组中的foreach循环的主要内容,如果未能解决你的问题,请参考以下文章

详细讲解foreach循环的用法

foreach循环中的一维和多维数组

PHP中使用foreach循环读取数组数据的方法

java使用foreach语句遍历二维数组如何实现?

java中何用for循环将一个二维数组的值付给另外一个二维数组

SwiftUI ForEach 获取二维数组中的元素和索引