C++ 创建具有n个维度的多维数组
我一直在想,是否有可能让用户根据给定的数字来决定一个数组应该有多少“维度” 设C++ 创建具有n个维度的多维数组,c++,arrays,C++,Arrays,我一直在想,是否有可能让用户根据给定的数字来决定一个数组应该有多少“维度” 设n为维度数,用户将键入其值。 它将创建一个n维数组 例如:对于n=5,它将创建一个名为list的数组,如下所示:intlist[size1][size2][size3][size4][size5]。 用户仍然会提到大小变量,但这实际上是第2部分 我想知道在声明数组之后,是否可以向数组添加更多维度。如果不是,我想找到一个解决这个问题的方法。 < P> C++语言没有提供可变大小或可变尺寸数组。 但是,您可以创建一个类来封
n
为维度数,用户将键入其值。
它将创建一个n维数组
例如:对于n=5
,它将创建一个名为list的数组,如下所示:intlist[size1][size2][size3][size4][size5]
。
用户仍然会提到大小变量,但这实际上是第2部分
我想知道在声明数组之后,是否可以向数组添加更多维度。如果不是,我想找到一个解决这个问题的方法。 < P> C++语言没有提供可变大小或可变尺寸数组。 但是,您可以创建一个类来封装这些行为 重要的特征是尺寸。您可以使用
std::vector
跟踪每个维度的元素数量;例如,{3,4,5}
表示三维矩阵,其中最内层维度的秩为3,中间维度为4,外部维度为5
使用模板化向量或deque为元素分配空间。所需的元素数是维度列组的乘积。(您可以使用带有乘法运算符的std::accumulate
,在秩向量上计算此值。)
接下来,您将需要一个方法,该方法获取一些对象(例如,int向量),该对象向MD数组提供访问元素所需的所有索引。您可以使用一些奇特的模板元编程来提供接受可变数量参数的重载
所有这些都是在一些非常专业化的用途之外,如:你正在编写数学软件,允许用户玩这些东西。 < P> C++语言没有提供可变大小或可变尺寸数组。< /P> 但是,您可以创建一个类来封装这些行为 重要的特征是尺寸。您可以使用
std::vector
跟踪每个维度的元素数量;例如,{3,4,5}
表示三维矩阵,其中最内层维度的秩为3,中间维度为4,外部维度为5
使用模板化向量或deque为元素分配空间。所需的元素数是维度列组的乘积。(您可以使用带有乘法运算符的std::accumulate
,在秩向量上计算此值。)
接下来,您将需要一个方法,该方法获取一些对象(例如,int向量),该对象向MD数组提供访问元素所需的所有索引。您可以使用一些奇特的模板元编程来提供接受可变数量参数的重载
除了一些非常专门的用途之外,所有这些都是多余的,例如:您正在编写类似Mathematica的软件,允许用户玩这些东西。您可能对我几个月前实现的一个数组类感兴趣,该类旨在为数组提供一种模仿matlab数组的语法。它利用initilizer_list语法,允许使用
Array<double> array({10, 20, 30});
甚至可以使用
array.getSlice({___, 3, 4});
其中“\uuuuuuuuu”用作通配符
有关更多信息,请参见:
实现:您可能对我几个月前实现的一个数组类感兴趣,该类旨在为数组提供一种语法,该语法模仿matlab数组。它利用initilizer_list语法,允许使用
Array<double> array({10, 20, 30});
甚至可以使用
array.getSlice({___, 3, 4});
其中“\uuuuuuuuu”用作通配符
有关更多信息,请参见:
实现:对象解决方案让用户选择维度数。有点健壮,我的C++可能不是最好的,但是它很有趣。code>nvector表示T类型元素的可调整大小(在维度和每个维度中的元素计数中)数组,尽管只实现了一些调整大小的函数
narray
是相同的,但尺寸的数量不可调整。它围绕着使用单个连续数组重新计算多维数组的索引位置的思想工作
#include <cstdio>
#include <vector>
#include <iostream>
#include <cstddef>
#include <cstdarg>
#include <algorithm>
#include <numeric>
#include <cassert>
#include <memory>
#include <cstring>
using namespace std;
template<typename T>
class narray {
public:
static size_t compute_size(initializer_list<size_t>& dims) {
return accumulate(dims.begin(), dims.end(), 1, multiplies<size_t>());
}
static size_t compute_size(vector<size_t>& dims) {
return accumulate(dims.begin(), dims.end(), 1, multiplies<size_t>());
}
static size_t compute_distance(vector<size_t>& dims) {
return dims.size() > 1 ? dims[1] : 1;
}
static vector<size_t> remove_one_dim(vector<size_t> dims_) {
return vector<size_t>(dims_.begin() + 1, dims_.end());
}
narray(initializer_list<size_t> dims, T* data) :
dims_(dims), data_(data) {}
narray(vector<size_t> dims, T* data) :
dims_(dims), data_(data) {}
T operator*() {
return *data_;
}
T* operator&() {
return data_;
}
void operator=(T v) {
if (dims_.size() != 0)
throw runtime_error(__PRETTY_FUNCTION__);
*data_ = v;
}
void operator=(initializer_list<T> v) {
if (v.size() > size())
throw runtime_error(__PRETTY_FUNCTION__);
copy(v.begin(), v.end(), data_);
}
T* data() {
return data_;
}
T* data_last() {
return &data()[compute_size(dims_)];
}
size_t size() {
return compute_size(dims_);
}
size_t size(size_t idx) {
return dims_[idx];
}
narray<T> operator[](size_t idx) {
if (dims_.size() == 0)
throw runtime_error(__PRETTY_FUNCTION__);
return narray<T>(remove_one_dim(dims_),
&data_[idx * compute_distance(dims_)]);
}
class iterator {
public:
iterator(initializer_list<size_t>& dims, T* data) :
dims_(dims), data_(data) { }
iterator(vector<size_t>& dims, T* data) :
dims_(dims), data_(data) { }
iterator operator++() {
iterator i = *this;
data_ += compute_distance(dims_);
return i;
}
narray<T> operator*() {
return narray<T>(remove_one_dim(dims_), data_);
}
bool operator!=(const iterator& rhs) {
if (dims_ != rhs.dims_)
throw runtime_error(__PRETTY_FUNCTION__);
return data_ != rhs.data_;
}
private:
vector<size_t> dims_;
T* data_;
};
iterator begin() {
return iterator(dims_, data());
}
iterator end() {
return iterator(dims_, data_last());
}
private:
vector<size_t> dims_;
T* data_;
};
template<typename T>
class nvector {
public:
nvector(initializer_list<size_t> dims) :
dims_(dims), data_(narray<T>::compute_size(dims)) {}
nvector(vector<size_t> dims) :
dims_(dims), data_(narray<T>::compute_size(dims)) {}
nvector(initializer_list<size_t> dims, T* data) :
dims_(dims), data_(data) {}
nvector(vector<size_t> dims, T* data) :
dims_(dims), data_(data) {}
T* data() {
return data_.data();
}
T* data_last() {
return &data()[narray<T>::compute_size(dims_)];
}
size_t size() {
return narray<T>::compute_size(dims_);
}
narray<T> operator&() {
return narray<T>(dims_, data());
}
narray<T> operator[](size_t idx) {
if (dims_.size() == 0)
throw runtime_error(__PRETTY_FUNCTION__);
return narray<T>(narray<T>::remove_one_dim(dims_),
&data()[idx * narray<T>::compute_distance(dims_)]);
}
void operator=(initializer_list<T> v) {
if (v.size() > size())
throw runtime_error(__PRETTY_FUNCTION__);
copy(v.begin(), v.end(), data_.begin());
}
auto begin() {
return typename narray<T>::iterator(dims_, data());
}
auto end() {
return typename narray<T>::iterator(dims_, data_last());
}
// add and remove dimensions
void dimension_push_back(size_t dimsize) {
dims_.push_back(dimsize);
data_.resize(size());
}
void dimension_pop_back() {
dims_.pop_back();
data_.resize(size());
}
// TODO: resize dimension of index idx?
private:
vector<size_t> dims_;
vector<T> data_;
};
int main()
{
nvector<int> A({2, 3});
A = { 1,2,3, 4,5,6 };
assert(A.size() == 6);
assert(&A[0] == &A.data()[0]);
assert(&A[0][0] == &A.data()[0]);
assert(&A[1] == &A.data()[3]);
assert(&A[0][1] == &A.data()[1]);
assert(&A[1][1] == &A.data()[4]);
cout << "Currently array has " << A.size() << " elements: " << endl;
for(narray<int> arr1 : A) { // we iterate over arrays/dimensions
for(narray<int> arr2 : arr1) { // the last array has no dimensions
cout << "elem: " << *arr2 << endl;
}
}
cout << endl;
// assigment example
cout << "Now it is 4: " << *A[1][0] << endl;
A[1][0] = 10;
cout << "Now it is 10: " << *A[1][0] << endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
模板
narray类{
公众:
静态大小\u t计算大小(初始值设定项\u列表和dims){
返回累加(dims.begin(),dims.end(),1,乘法());
}
静态大小\u t计算大小(向量和dims){
返回累加(dims.begin(),dims.end(),1,乘法());
}
静态大小计算距离(矢量和dims){
返回dims.size()>1?dims[1]:1;
}
静态矢量删除一个尺寸(矢量尺寸){
返回向量(dims_.begin()+1,dims_.end());
}
narray(初始值设定项列表dims,T*数据):
dims_(dims),data_(data){}
narray(矢量dims,T*数据):
dims_(dims),data_(data){}
T算子*(){
返回*数据;
}
T*运算符&(){
返回数据;
}
无效运算符=(tV){
如果(暗度大小()!=0)
抛出运行时错误(函数);
*数据=v;
}
void运算符=(初始值设定项\列表v){
如果(v.size()>size())
抛出运行时错误(函数);
复制(v.begin()、v.end()、数据);
}
T*数据(){
返回数据;
}
T*data_last(){
返回和数据()[计算尺寸(dims)];
}
大小{
返回计算大小(dims);
}
尺寸(尺寸idx){
返回dims_ux[idx];
}
narray运算符[](大小\u t idx){
如果(dims_u2;.size()==0)
抛出运行时错误(函数);
返回narray(移除一个dim(dims),
&数据[idx*计算距离(dims)];