基于多维数组的范围
range-based for on multi-dimensional array
我的嵌入式系统得到了一个支持 C++11 的 g++ 版本,所以我一直在清理代码
for( uint16_t* p = array; p < (&array)[1]; ++p ) {
*p = fill_value;
}
自
for( uint16_t& r : array ) {
r = fill_value;
}
这更具可读性。
是否有一个基于范围的 for 循环,它可以在array2[m][n]
的所有元素上运行?
旧版本是
for( int16_t* p = array2[0]; p < (&array2)[1][0]; ++p ) {
*p = fill_value;
}
而且我不想要嵌套循环,除非保证编译器会扁平化它们。
(FWIW,编译器是 GNU 4.7.4 Linaro g++ ARM 交叉编译器,随 TI Code Composer Studio 6.0.0 一起提供(
例如,有多种方法可以打印和操作多维数组的值。
int arr[2][3] = { { 2, 3, 4 }, { 5, 6, 7} };
第一种方法,
size_t count = 0 ;
for( auto &row : arr)
for(auto &col : row)
col = count ++;
在第一个 for 循环中,我们指的是两个数组。然后在第二个数组中,我们分别引用了这些子数组的 3 个元素。我们还将计数分配给 col。因此,它会迭代到子数组的下一个元素。
第二种方法,
for( auto &row : arr)
for( auto col : row)
cout << col << endl;
我们在第一个循环中引用,因为我们希望避免数组到指针的转换。
如果这样做(错误情况:第一个for循环不是引用(,
for( auto row : arr) // program won't compile
for( auto col : row)
在这里,我们在行中有 int *。当我们到达第二个 for 循环时。因为行现在是 int * 而不是列表,所以程序不会编译。你必须创建一个列表,然后只有我们可以将其传递给ranged for loop并使用它来迭代该列表。
vector<int> list = { *(row+0) , *(row+1) , *(row+ 2) } ;
现在我们可以使用该列表进行迭代
for ( ----- : list)
for ( auto &a : array )
{
for ( int &x : a ) x = fill_value;
}
编辑:您可以尝试以下方法
const size_t n = 2;
const size_t m = 3;
int a[n][m] = { { 1, 2, 3 }, { 4, 5, 6 } };
for ( auto &x : reinterpret_cast<int ( & )[n * m]>( a ) ) x = 10;
for ( auto x : reinterpret_cast<int ( & )[n * m]>( a ) ) std::cout << x << ' ';
std::cout << std::endl;;
输出为
10 10 10 10 10 10
这种方法的优点是,您可以重新解释任何多维数组,而不仅仅是二维数组。例如
int a[n][m][k] = { /* some initializers */ };
for ( auto x : reinterpret_cast<int ( & )[sizeof( a ) / sizeof( ***a )]>( a ) )
{
std::cout << x << ' ';
}
std::cout << std::endl;;
下面是一些将填充任意数组(静态已知大小(的代码:
#include <algorithm>
#include <iterator>
#include <type_traits>
template <typename T>
void fill_all(T & a, typename std::remove_all_extents<T>::type v);
template <typename T>
void fill_all_impl(T & a, typename std::remove_all_extents<T>::type v, std::false_type);
template <typename T>
void fill_all_impl(T & a, typename std::remove_all_extents<T>::type v, std::true_type)
{
for (auto & x : a)
fill_all(x, v);
}
template <typename T>
void fill_all_impl(T & a, typename std::remove_all_extents<T>::type v, std::false_type)
{
std::fill(std::begin(a), std::end(a), v);
}
template <typename T>
void fill_all(T & a, typename std::remove_all_extents<T>::type v)
{
fill_all_impl(a, v, std::is_array<typename std::remove_extent<T>::type>());
}
用法示例:
int a[3][4][2];
fill_all(a, 10);
结合弗拉德和普拉托里安的部分答案,我决定使用:
template<typename T, size_t N, size_t M>
auto flatten(T (&a)[M][N]) -> T (&)[M*N] { return reinterpret_cast<T (&)[M*N]>(a); }
for( int16_t& r : flatten(array2) ) {
r = fill_value;
}
@Ben Voigt 答案的更一般的变体(可以应用于 n 维数组(:
template
<
typename Array,
typename Element = typename std::remove_all_extents<Array>::type,
std::size_t Size = sizeof(Array) / sizeof(Element),
typename FlattenedArray = Element (&)[Size]
>
constexpr FlattenedArray Flatten(Array &a)
{
return reinterpret_cast<FlattenedArray>(a);
}
template
<
typename Array,
typename Element = typename std::remove_all_extents<Array>::type
>
void FillArray(Array& a, Element v)
{
for (Element& e : Flatten(a))
{
e = v;
}
}
// ...
int a[2][3][5];
int d = 42;
FillArray(a, d);
活生生的例子。
比 SB@Kerrek 的解决方案更简单(可能效率较低(:
#include <type_traits>
template <typename Type>
void FillArray(Type& e, Type v)
{
e = v;
}
template <typename Type, std::size_t N>
void FillArray(Type (&a)[N], typename std::remove_all_extents<Type>::type v)
{
for (Type& e : a)
{
FillArray(e, v);
}
}
使用示例:
int a[2][3][5];
FillArray(a, 42);
一个更通用的解决方案,允许将函子应用于多维数组的所有元素:
template <typename Type, typename Functor>
void ForEachElement(Type& e, Functor f)
{
f(e);
}
template <typename Type, std::size_t N, typename Functor>
void ForEachElement(Type (&a)[N], Functor f)
{
for (Type& e : a)
{
ForEachElement(e, f);
}
}
使用示例:
int a[2][3][5];
ForEachElement(a, [](int& e){e = 42;});
#include <iostream>
using namespace std;
int main() {
int arr[3][4];
// Initialising the 2D array
for(int i = 0; i < 3; i++){
for(int j = 0; j < 4; j++){
arr[i][j] = i * j + 10;
}
}
// Accessing elements of 2D array using range based for loop
for(auto &row: arr){
for(auto &col: row){
cout << col << " ";
}
cout << endl;
}
return 0;
}
- 并行用于C++17中数组索引范围内的循环
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 基于字节数组生成静态范围整数值
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 使用基于数组和范围的 For 循环替换一些基本代码行
- C++中循环和 C 样式数组的范围工作
- Excel 不愉快地显示大型 2D 范围公式数组
- 变量未在此范围内声明 数组线性搜索
- 如何使用基于范围的for循环迭代Rapidjson文档(它本身就是一个JSON数组)
- 对于多个查询,查找在 l 到 r 范围内具有相同元素的最长公共子数组
- 基于多维标准::数组的范围
- 从文件中读取选定的行范围并存储到数组中
- 从原始指针(衰减的 C 样式数组)和大小生成范围::视图
- C++ 如何在给定范围内将数组中的数字相加?
- 给定数组范围的选择排序问题
- C++ 从指定范围内的文件中读取数组
- 数组不会存储超出第一个空间的范围
- gcc8.2如何启用警告:数组下标在数组范围之上[-warray-bounds]
- 数组中的"Maximum Sum mod M"范围:求和和计数
- 检查一对值是否位于范围数组中的范围之间