C ++ 11动态分配的可变长度多维数组 [英] C++11 dynamically allocated variable length multidimensional array
问题描述
我一直在尝试创建可变长度的多维数组。据我了解,您不能在堆栈上创建可变长度数组,但是可以使用动态分配在C ++中创建一维可变长度数组。请纠正我,如果这是一个编译器扩展,但在带有--pedantic设置的clang和gcc上似乎可以正常工作。
I've been trying to create a variable length multidimensional array. As I understand, you can't create variable length arrays on the stack, but you can create 1D variable length arrays in C++ using dynamic allocation. Correct me if this is a compiler extension, but it seems to work fine on clang and gcc with --pedantic set.
int size = 10;
int *ary = new int[size]();
我试图将概念扩展到多维数组。这是我的结果。可能性1和2的问题在于它们需要使用constexpr,并且不能用于可变大小。是否可以让它们中的任何一个接受变量作为其大小?我知道可能性3,但是它缺少[] []访问权限,这正是我要寻找的。 p>
I tried to extend the concept to multidimensional arrays. Here are my results. The problem with possiblity 1 and 2 is that they require a constexpr and do not work with variable sizes. Is it possible to make either of them accept a variable as its size? I put possibility 3 as I am aware of it, but it lacks [][] access, which is what I'm looking for.
constexpr int constSize = 10;
//Possibility 1: Only works in C++11
//Creates CONTIGUOUS 2D array equivalent to array[n*n], but with [][] access
int (*ary1)[constSize] = new int[constSize][constSize]();
delete [] ary1;
//Possibility 2:
//Really horrible as it does NOT create a contiguous 2D array
//Instead creates n seperate arrays that are each themselves contiguous
//Also requires a lot of deletes, quite messy
int **ary2 = new int*[constSize];
for (int i = 0; i < n; ++i)
ary2[i] = new int[constSize];
for (int i = 0; i < n; ++i)
delete [] ary2;
delete [] ary2;
//Possibility 3:
//This DOES work with non-constexpr variable
//However it does not offer [][] access, need to access element using ary[i*n+j]
int *ary3 = new int[size*size];
delete [] ary3;
推荐答案
维数是固定的,因为类型 []
返回的内容基于维数而变化。通过重复的 []
和(...)
进行访问。第一个模仿C样式的数组查找。 (...)
语法必须完整(必须将 N
args传递给 N
维数组)。同时支持这两者的效率成本不高。
The number of dimensions is fixed, because the type of what []
returns changes based on the number of dimensions. Access is through both repeated []
and (...)
. The first mimics C-style array lookup. The (...)
syntax must be complete (it must pass N
args to an N
dimensional array). There is a modest efficiency cost to support both.
使用C ++ 14功能来节省冗长性。
Uses C++14 features to save on verbosity. None are essential.
使用带 0
n_dim_array
Using an an n_dim_array
with 0
dimensions will give bad results.
template<class T, size_t N>
struct array_index {
size_t const* dimensions;
size_t offset;
T* buffer;
array_index<T,N-1> operator[](size_t i)&&{
return {dimensions+1, (offset+i)* *dimensions, buffer};
}
template<class...Is, std::enable_if_t<sizeof...(Is) == N>>
T& operator()(size_t i, Is...is)&&{
return std::move(*this)[i](is...);
}
};
template<class T>
struct array_index<T,0> {
size_t const* dimension;
size_t offset;
T* buffer;
T& operator[](size_t i)&&{
return buffer[i+offset];
}
T& operator()(size_t i)&&{
return std::move(*this)[i];
}
};
template<class T, size_t N>
struct n_dim_array {
template<class...Szs, class=std::enable_if_t<sizeof...(Szs)==N>>
explicit n_dim_array( Szs... sizes ):
szs{ { static_cast<size_t>(sizes)... } }
{
size_t sz = 1;
for( size_t s : szs )
sz *= s;
buffer.resize(sz);
}
n_dim_array( n_dim_array const& o ) = default;
n_dim_array& operator=( n_dim_array const& o ) = default;
using top_level_index = array_index<T,N-1>;
top_level_index index(){return {szs.data(),0,buffer.data()};}
auto operator[]( size_t i ) {
return index()[i];
}
using const_top_level_index = array_index<const T,N-1>;
const_top_level_index index()const{return {szs.data(),0,buffer.data()};}
auto operator[]( size_t i ) const {
return index()[i];
}
template<class...Is,class=std::enable_if_t<sizeof...(Is)==N>>
T& operator()(Is...is){
return index()(is...);
}
template<class...Is,class=std::enable_if_t<sizeof...(Is)==N>>
T const& operator()(Is...is) const {
return index()(is...);
}
private:
n_dim_array() = delete;
std::array<size_t,N> szs;
std::vector<T> buffer;
};
不支持 for(:)
循环迭代。编写迭代器并不难:我可以在 array_index
中完成。
Does not support for(:)
loop iteration. Writing an iterator isn't that hard: I'd do it in array_index
.
这篇关于C ++ 11动态分配的可变长度多维数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!