[英]dynamic allocating memory for 3d array that uses minimum memory and in contiguous form in c++?
我想建立一个nx,ny,nz约为200的3D nx * ny * nz矩阵,所以我必须使用动态分配,因为我有很多这些矩阵,我需要以一种使用最小内存的方式构建这些矩阵我怎么可能这样做,我怎么能建立连续的形式?
使用C ++ 11:
template<typename T,size_t M,size_t N,size_t O>
using Matrix3D = std::array<std::array<std::array<T,O>,N>,M>;
std::unique_ptr<Matrix3D<double,200,200,200>> mat(new Matrix3D<double,200,200,200>);
(*mat)[m][n][o] = 10.0;
如果编写make_unique
函数,变量声明将变为:
auto mat = std::make_unique<Matrix3D<double,200,200,200>>();
所以整个程序可能看起来像:
#include <memory> // std::unique_ptr for convenient and exception safe dynamic-memory management
#include <array> // std::array because it behaves much better than raw arrays
template<typename T,size_t M,size_t N,size_t O>
using Matrix3D = std::array<std::array<std::array<T,O>,N>,M>;
// A simple `make_unique`
template<typename T,typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
int main() {
auto mat = make_unique<Matrix3D<double,200,27,200>>();
(*mat)[199][26][199] = 10.0; // store 10.0 in the last element
}
请记住,这是C ++ 11,有些编译器还没有实现我正在使用的所有功能。 特别是我所知道的唯一支持模板别名的发布的编译器( using Matrix3D =
行)是clang 3.0。 下一版GCC将支持它。 GCC和Clang都支持变量模板(用于实现make_unique
),但VS11中不支持MSVC。
这是一个仅使用广泛支持的* C ++ 11功能的版本:
#include <memory>
#include <array>
template<typename T,size_t M,size_t N,size_t O>
struct Matrix3D {
std::array<std::array<std::array<T,O>,N>,M> array;
};
// A simple `make_unique` that supports only zero-argument construction.
template<typename T>
std::unique_ptr<T> make_unique() {
return std::unique_ptr<T>(new T);
}
int main() {
auto mat = make_unique<Matrix3D<double,200,27,200>>();
mat->array[199][26][199] = 10.0; // store 10.0 in the last element
}
*
广泛支持至少意味着最新版本的GCC和MSVC。
如果维度在编译时是已知的,你可以使用new
分配对象,虽然我可能会把它放在一个结构中因为我在数组和指针之间保持混合类型(我几乎没有直接使用它们):
struct array3d {
double array[200][200][200];
};
std::auto_ptr<areay3d> array(new array3d);
显然,数组维度可以成为模板参数。
如果仅在运行时确定维度,则需要分配连续的double
数组并自行执行数组下标计算。 如果类访问元素,这可能也会成为一个集合:3d数组的下标运算符将返回对2d数组的引用,等等std::valarray<double>
旨在帮助解决这个问题,并且有针对此类的增强类这也是。
您可以在std::vector
周围编写一个包装器,并重载operator()
来访问矩阵元素。 元素在1D std::vector
连续存储, operator()
将3D索引转换为std::vector
的1D索引。 如果矩阵是2D,这就是从2D到1D的映射看起来像:
| 1 2 3 |
| 4 5 6 | ---> [1 2 3 4 5 6 7 8 9]
| 7 8 9 |
这种排序称为行主要 。
这是一个重载operator()
以将3D索引转换为行主要1D索引的类的示例:
#include <iostream>
#include <vector>
template <class T>
class Matrix3D
{
public:
Matrix3D(size_t m, size_t n, size_t o)
: m_(m), n_(n), o_(o), data_(m*n*o) {}
T& operator()(size_t i, size_t j, size_t k)
{
return data_[(i * n_ * o_) + (j * o_) + k];
}
const T& operator()(size_t i, size_t j, size_t k) const
{
return data_[(i * n_ * o_) + (j * o_) + k];
}
private:
std::vector<T> data_;
size_t m_, n_, o_;
};
int main()
{
Matrix3D<float> m(4, 3, 2);
m(0,0,0) = 12.3f;
m(3,2,1) = 45.6f;
std::cout << m(0,0,0) << " " << m(3,2,1) << "\n";
}
Boost.MultiArray库与此基本相同(以及更多),但可用于任何维度N.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.