在C+中动态创建多维数组+; < >在C++中动态创建多维数组的好方法(理解习惯/良好实践)。

在C+中动态创建多维数组+; < >在C++中动态创建多维数组的好方法(理解习惯/良好实践)。,c++,arrays,multidimensional-array,dynamic-allocation,C++,Arrays,Multidimensional Array,Dynamic Allocation,例如,假设我有树整数w,h和d,我想创建一个数组MyEnum my_数组[w][h][d]。(当然,w、h和d在编译时是未知的) 最好使用嵌套的std::vector还是使用new或其他什么 附加问题:是否也可以动态设置维度?通常,嵌套std::vector不是一个好主意。通常,更好的方法是分配内存,将整个多维数组作为一个连续块保存,然后像多维数组一样索引到其中。这个内存块可以通过new进行分配,但除非您需要对其分配方式进行精确控制(自定义分配器),否则我建议使用单个std::vector 创建

例如,假设我有树整数
w
h
d
,我想创建一个数组
MyEnum my_数组[w][h][d]
。(当然,w、h和d在编译时是未知的)

最好使用嵌套的std::vector还是使用new或其他什么


附加问题:是否也可以动态设置维度?

通常,嵌套
std::vector
不是一个好主意。通常,更好的方法是分配内存,将整个多维数组作为一个连续块保存,然后像多维数组一样索引到其中。这个内存块可以通过
new
进行分配,但除非您需要对其分配方式进行精确控制(自定义分配器),否则我建议使用单个
std::vector

创建一个类来管理这样一个可以动态设置维度数量的资源并不困难。组织这样一个类的好方法是跟踪分配的内存、每个维度的大小以及每个维度的步幅模式。步幅描述了为了沿着给定维度到达下一个元素,必须增加多少个元素

这允许高效的索引(只是指针算法),以及非常高效的重塑:只要元素数量不变,这只需要更改形状和跨距数组


示例:

这里有一个非常基本的类,它将存储这样一个动态的多维数组
double
s。它以行主顺序存储数据,这意味着最后一个索引变化最快。因此,对于二维数组,第一行连续存储,第二行紧跟其后,依此类推

如果需要,可以重塑阵列形状,更改维数。还显示了基本元素访问
操作符[]
。这个类没有什么特别之处,但是您可以扩展它以提供您想要的任何功能,例如迭代器、数据的数学运算、I/O操作符等

/*! \file dynamic_array.h
 * Basic dynamic multi-dimensional array of doubles.
 */

#ifndef DYNAMIC_ARRAY_H
#define DYNAMIC_ARRAY_H

#include <vector>
#include <numeric>
#include <functional>

class
dynamic_array
{
    public:
        dynamic_array(const std::vector<int>& shape)
            : m_nelem(std::accumulate(shape.begin(), shape.end(),
                        1, std::multiplies<int>()))
            , m_ndim(shape.size())
            , m_shape(shape)
        {
            compute_strides();
            m_data.resize(m_nelem, 0.0);
        }

        ~dynamic_array()
        {
        }

        const double& operator[](int i) const
        {
            return m_data.at(i);
        }

        double& operator[](int i)
        {
            return m_data.at(i);
        }

        const double& operator[](const std::vector<int>& indices) const
        {
            auto flat_index = std::inner_product(
                    indices.begin(), indices.end(),
                    m_strides.begin(), 0);
            return m_data.at(flat_index);
        }

        double& operator[](const std::vector<int>& indices)
        {
            auto flat_index = std::inner_product(
                    indices.begin(), indices.end(),
                    m_strides.begin(), 0);
            return m_data.at(flat_index);
        }

        void reshape(const std::vector<int>& new_shape)
        {
            auto new_nelem = std::accumulate(
                    new_shape.begin(), new_shape.end(),
                    1, std::multiplies<int>());
            if (new_nelem != m_nelem) {
                throw std::invalid_argument("dynamic_array::reshape(): "
                        "number of elements must not change.");
            }
            m_nelem = new_nelem;
            m_ndim = new_shape.size();
            m_shape = new_shape;
            compute_strides();
        }

        const std::vector<int>& shape() const
        {
            return m_shape;
        }

        const std::vector<int>& strides() const
        {
            return m_strides;
        }

        int ndim() const
        {
            return m_ndim;
        }

        int nelem() const
        {
            return m_nelem;
        }

    private:
        int m_ndim;
        int m_nelem;
        std::vector<int> m_shape;
        std::vector<int> m_strides;
        std::vector<double> m_data;

        void compute_strides()
        {
            m_strides.resize(m_ndim);
            m_strides.at(m_ndim - 1) = 1;
            std::partial_sum(m_shape.rbegin(),
                    m_shape.rend() - 1,
                    m_strides.rbegin() + 1,
                    std::multiplies<int>());
        }
};

#endif // include guard
/*\文件dynamic_array.h
*基本动态多维双精度阵列。
*/
#ifndef动态数组
#定义动态数组
#包括
#包括
#包括
班
动态数组
{
公众:
动态数组(const std::vector&shape)
:m_nelem(std::累加(shape.begin(),shape.end(),
1,std::multiples())
,m_ndim(shape.size())
,m_形状(形状)
{
计算步幅();
m_data.resize(m_nelem,0.0);
}
~dynamic_数组()
{
}
常量双精度和运算符[](int i)常量
{
在(i)处返回m_数据;
}
双重运算符(&O)[](int i)
{
在(i)处返回m_数据;
}
常量双精度和运算符[](常量标准::向量和索引)常量
{
自动展平指数=标准::内部产品(
index.begin(),index.end(),
m_跨步。开始(),0);
返回m_数据.at(平面索引);
}
双精度和运算符[](常量标准::向量和索引)
{
自动展平指数=标准::内部产品(
index.begin(),index.end(),
m_跨步。开始(),0);
返回m_数据.at(平面索引);
}
空洞重塑(常量标准::向量和新形状)
{
自动新建\u nelem=std::累加(
新建形状。开始(),新建形状。结束(),
1,std::multiples());
if(new_nelem!=m_nelem){
抛出std::无效的_参数(“动态_数组::重塑():”
“元素的数量不得改变。”);
}
m_nelem=新的_nelem;
m_ndim=新的_shape.size();
m_形状=新的_形状;
计算步幅();
}
常量std::vector&shape()常量
{
返回m_形;
}
常量std::向量和步长()常量
{
回程迈步;
}
int ndim()常量
{
返回m_ndim;
}
int nelem()常量
{
返回m_nelem;
}
私人:
国际货币基金组织;
国际货币基金组织;
std::向量m_形;
std::向量m_跨步;
std::向量m_数据;
void计算步数()
{
m_跨步。调整大小(m_ndim);
(m_ndim-1)=1时的m_步长;
std::partial_sum(m_shape.rbegin(),
m_shape.rend()-1,
m_跨步。rbegin()+1,
std::multiples());
}
};
#endif//包括防护罩
下面是该功能的基本演示

/*! \file test.cc
 * Basic test of the dynamic_array class.
 */
#include "dynamic_array.h"
#include <iostream>

int main(int /* argc */, const char * /* argv */[])
{
    dynamic_array arr({2, 3});
    std::cout << "Shape: { ";
    for (auto& each : arr.shape())
        std::cout << each << " ";
    std::cout << "}" << std::endl;

    std::cout << "Strides: { ";
    for (auto& each : arr.strides())
        std::cout << each << " ";
    std::cout << "}" << std::endl;

    // Reshape array, changing number of dimensions, but
    // keeping number of elements constant.
    arr.reshape({6});
    std::cout << "Shape: { ";
    for (auto& each : arr.shape())
        std::cout << each << " ";
    std::cout << "}" << std::endl;

    // Verify that the stride pattern has now also changed.
    std::cout << "Strides: { ";
    for (auto& each : arr.strides())
        std::cout << each << " ";
    std::cout << "}" << std::endl;

    return 0;
}
/*\文件test.cc
*动态数组类的基本测试。
*/
#包括“dynamic_array.h”
#包括
int main(int/*argc*/,const char*/*argv*/[])
{
动态数组arr({2,3});

谢谢你,这就是我一直在寻找的答案!