我正在寻找一种在C ++中声明一个5维数组的优雅方法。
每个嵌套的向量都有已知的大小,所以我开始做:
std::vector<std::vector<std::vector<std::vector<double>>>> myDblVec;
然后假设我知道所有尺寸:
myDblVec.resize(dim1);
for (int d1 = 0; d1 != dim1; d1++) {
myDblVec[d1].resize[dim2];
for (int d2 = 0; d2 != dim2; d2++) {
myDblVec[d1][d2].resize(dim3)
for (int d3 = 0; d3 != dim3; d3++) {
myDblVec[d1][d2][d3].resize(dim4);
}
}
}
我正在寻找一个1-liner或更少&#39; heavy&#39;声明这个数组。
答案 0 :(得分:1)
您可以使用std::array
,假设在编译时已知大小:
std::array<std::array<std::array<std::array<double, dim4>, dim3>, dim2>, dim1> myDblArray;
答案 1 :(得分:1)
如果您获得尺寸运行时间,例如
myDblVec = std::vector<std::vector<std::vector<std::vector<double>>>>(dim1,
std::vector<std::vector<std::vector<double>>>(dim2,
std::vector<std::vector<double>>(dim3,
std::vector<double>>(dim4, 0.0))));
答案 2 :(得分:1)
如果您对C ++ 11之前的版本不太满意,可以编写一个简单的可变参数模板:
template <typename T, size_t... N> struct NestedArray;
template <typename T, size_t N> struct NestedArray<T, N> {
using type = array<T, N>;
};
template <typename T, size_t N, size_t... Rest>
struct NestedArray<T, N, Rest...> {
using type = array<typename NestedArray<T, Rest...>::type, N>;
};
现在,您可以将数组定义为NestedArray<double, dim1, dim2, dim3, dim4>::type
。
答案 3 :(得分:1)
std::vector<T>
将大小作为第一个构造函数参数。您可以利用这一点,并使用
make_vector_t<double, 5> myDblVec(init_vector<double, 5>(dim1, dim2, dim3, dim4, dim5));
这需要一些基础设施来创建类型并初始化元素。当然,这个基础设施是合理的直接(虽然我还没有编译它 - 目前我只是使用移动设备,也就是说,几乎肯定有一个错字,但整体方法应该是owrk):< / p>
template <typename T, int Dim> struct make_vector;
template <typename T, int Dim>
using make_vector_t = typename make_vector<T, Dim>::type;
template <typename T>
struct make_vector<T, 0> { using type = T; }
template <typename T, int Dim>
struct make_vector { using type = std::vector<make_vector_t<T, Dim-1>>; }
template <typename T, int Dim, typename Arg, typename... Args>
auto init_vector(Arg size, Args... sizes) -> make_vector_t<T, Dim-1> {
return make_vector_t<T, Dim>(size, init_vector<T, Dim-1>(sizes...);
}
答案 4 :(得分:0)
vector<vector>
这真的是件好事吗?你在考虑一个行可以有独立长度的矩阵吗?如果答案是“否”,那么考虑一下你只需要一个普通向量的概念,它的大小是5维的乘积,其元素位于
size_t at(size_t a, size_t b, size_t c, size_t d, size_t e, size_t A, size_t B, size_t C, size_t D, size_t E)
{ return e+d*E+c*D*E+b*C*D*E+a*B*C*D*E; }
(注意:大写字母是大小)。
通过使用varadics,您可以轻松地将其概括为任意数量的维度:
template<class... I>
size_t at(size_t r, size_t R, size_t c, size_t C, I... i)
{ return size_at(r*C+c,i...); }
size_t at(size_t c, size_t C)
{ return c; }
您还可以将所有这些嵌入到经常性的课程中
template<class T, size_t Rank>
class grid
{
grid<T,Rank-1> m; size_t C;
public:
template<class... I>
grid(size_t r, size_t c, I... i) :m(r*c,i...) :C(c) {}
template<class... I>
T& operator()(size_t r, size_t c, I... i)
{ return m(r*C+c,i...); }
template<class... I>
const T& operator()(size_t r, size_t c, I... i) const
{ return m(r*C+c,i...); }
};
template<class T>
class grid<T,1>
{
std::vector<T> m;
public:
explicit grid(size_t n) :m(n) {}
T& operator()(size_t i) { return m[i]; }
const T& operator()(size_t i) const { return m[i]; }
};
你可以宣布一个grid<5> a(3,2,4,5,3);
并将其元素作为a(x,y,z,w,t);
访问,无论x在0..2中是什么,y在0..1中是什么,z在0..3中是否在0..4中,而t在0..2中是什么;
答案 5 :(得分:0)
如果您非常需要多维数组,请考虑将必须处理它们的内容移动到使用C而不是C ++的单独源文件中。您可以在语言之间轻松连接,并在C中分配动态大小的5D数组就像
一样简单double (*fiveDArray)[dim2][dim3][dim4][dim5] = malloc(dim1 * sizeof(*fiveDArray));
用法与嵌套的std::vector<>
几乎相同,您需要记住的是在完成数组后调用free()
。如果您需要零初始化数组,请将malloc()
替换为calloc()
。作为一个额外的好处,C多维数组的连续性在CPU缓存上比使用std::vector<>
更好,并且索引更快,因为只有一个指向追逐的指针。
C ++不允许这样做,因为这种语言将数组维度限制为编译时常量。另一方面,C在C99标准中取消了这一限制,甚至允许typedef
中的动态数组大小:
void foo(size_t dim1, size_t dim2, size_t dim3, size_t dim4, size_t dim5) {
typedef double FourDSlice[dim2][dim3][dim4][dim5];
FourDSlice *fiveDArray = malloc(dim1 * sizeof(*fiveDArray));
...
}
完全合法的C99,在C ++中无法做到。