我有一个关于递归定义数组中数据的排序和对齐的问题。请考虑以下代码
template<int rank, int dim, class T> struct recursive_array;
template<int dim,class Tp>
struct recursive_array <0,dim,Tp> {
using value_type = Tp;
recursive_array<0,dim,Tp>& operator=(Tp const& val)
{
value = val;
return *this;
}
operator Tp &() {return value;}
value_type value;
};
template<int rank, int dim, class Tp>
struct recursive_array {
using value_type = recursive_array<rank-1, dim, Tp>;
recursive_array<0,dim,Tp>& operator=(Tp const& val)
{
for(int i = 0; i < dim; ++i)
values[i] = val;
return *this;
}
value_type& operator[] (unsigned int const i)
{
return values[i];
}
value_type values[dim];
};
recursive_array
的唯一成员是recursive_array
rank-1
的普通旧c阵列。在递归结束时,即rank == 0
,唯一的成员value
包含实际数据。这种技术在有限元库deal.II中用于描述一类通用的Tensors,以防万一你想知道我为什么不使用普通的c风格数组。
现在让我们使用recursive_array
类和一个普通的旧式c风格数组定义一个2 x 2 x 2 x 2的整数数组,并比较它们在内存中的数据布局
//main.cc
#include<iostream>
int main () {
recursive_array<4,2,int> arr;
int carr[2][2][2][2];
for(int i = 0; i < 2; ++i)
for(int j = 0; j < 2; ++j)
for(int k = 0; k < 2; ++k)
for(int l = 0; l < 2; ++l){
int idx = i*8 + j*4 + k*2 + l;
arr[i][j][k][l] = idx;
carr[i][j][k][l] = idx;
std::cout << ((int*)&(arr[0][0][0][0]))[idx] << " "
<< ((int*)&(carr[0][0][0][0]))[idx] << std::endl;
}
return 0;
}
创建以下输出
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
使用recursive_array
时,数据似乎会连续存储,因为c样式数组就是这种情况。这符合deal.II documentation,但也说
显示条目的顺序[...]未定义。
或者我错过了什么?
但是,独立于本文档所说的内容,我有兴趣了解上述代码的工作原理。
非常感谢你!
我使用带有-std=c++11 -O0
和-std=c++11 -O3
标志的gcc 6.3编译了上述代码,两次都得到了相同的结果。
答案 0 :(得分:1)
我是主要交易之一.II开发商;我没有为ArrayView
编写特定的构造函数,但我想我仍然可以回答你的问题。
对于记录:deal.II
邮件列表非常活跃,是提出这类问题的好地方。
该评论是沙漏,并且简单地说明我们可能会在未来的某个时刻修改Tensor
的布局:因此,明确不鼓励在完全消除时所依赖的顺序。
几年前(2015年秋季),我们重写了整个Tensor
课程,其定义基本上与您的示例相同;与operator[]
和朋友的公共接口被重新实现以保持兼容性,但底层存储顺序改变了IIRC(我们从一些较低级别的硬编码到递归执行所有操作)。如果我们出于某种原因再次更改实现,那么内存中的顺序将会不同;因此评论。我认为该评论的作者试图提出的观点是“我们可能会改变未来的实施方式,所以不要依赖现在的事情顺序”。