2015-10-23 119 views
3

假设我想为多维数组中的每个数做一些事情。我发现你可以得到第一个数字的指针,然后使用指针加法。例如,下面的代码通过12输出数字1对多维数组进行迭代

double a[2][3][2] = {{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}}; 
double *p = &a[0][0][0]; 
for (int i = 0; i < 12; i++) 
    cout << *(p + i) << endl; 

是否unidiomatic考虑多维数组以这种方式是平?如果是这样,那么这样做的首选方式是什么?另外,是否有更简单的方法来编写double *p = &a[0][0][0];以获取多维数组中第一个数字的指针(与您可以只为一维数组编写double *p = a;一样)?

回答

6

是的,多维阵列保证是平坦的。但是,最好能提供这种类型的东西。如果你想在一个多维数组平放迭代,我觉得这是更好地推出一系列视图进去:

template <typename T> 
struct Flat { 
    auto begin() { return first(arr); } 
    auto end() { 
     return begin() + sizeof(arr)/sizeof(*begin()); 
    } 

    template <typename X> X* first(X& val) { return &val; } 
    template <typename X, size_t N> auto first(X(&val)[N]) { return first(*val); } 

    T& arr; 
}; 

template <typename T> 
Flat<T> flatten(T& arr) { 
    return Flat<T>{arr}; 
} 

,只需使用一个:

for (double d : flatten(a)) { 
    std::cout << d << std::endl; 
} 

否则,只其他声明p的方法与double *p = &***a;类似。我不确定是否成为三星级程序员的成就列表很高。

+2

加一个用于“三星程序设计” – vsoftco

+0

这难道不是太复杂了吗? – Numeri

+0

@Numeri不,不是真的。 – Barry

1

是的,多维数组总是可以被视为平坦的。此外,与一维数组相同,可以说double *p = reinterpret_cast<double*>(a)double *p = &a[0][0][0]相同。

多维数组,如果动态分配,可能不平坦。但是,那将是显而易见的,因为分配将由你完成。

+0

我试图'双* P = A;',它说'错误:不能转换 '双(*)[3] [2]' 到“双* '在初始化double * p = a;' –

+0

对不起,我忘记了在C++中你需要投射指针类型来匹配。我相应地更新了我的回答 – jayant

+1

谢谢,'double * p = reinterpret_cast (a)'似乎有效。 –

3

虽然它可以是非常有用知道一个多维数组实际上是平的,它通常会是unidiomatic指使用指针和指针运算它,因为它引入了更多的潜在错误和更难比读惯用的解决方案,下标符号。正因为如此,我建议使用这样的:

double a[2][3][2] = {{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}}; 

for (int i = 0; i < 2; i++) 
{ 
    for (int j = 0; j < 3; j++) 
    { 
     for (int k = 0; k < 2; k++) 
     { 
      cout << a[i][j][k] << endl; 
     } 
    } 
}