五维矢量声明

时间:2014-12-26 20:51:56

标签: c++ vector multidimensional-array

我正在寻找一种在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;声明这个数组。

6 个答案:

答案 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 ++中无法做到。