How would I go about dynamically allocating a multi-dimensional array?
如何动态分配多维数组?
12 个解决方案
#1
24
If you know the size of nested dimensions already, you can also literally allocate a multi dimensional array using new:
如果您已经知道了嵌套维度的大小,您还可以使用new来分配多维数组:
typedef int dimensions[3][4];
dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;
instead of 10
, a runtime determined value can be passed. Since it's not part of the type operator new returns, that's allowed. This is nice if you know the number of columns, but want to keep the number of rows variable, for example. The typedef makes it easier to read the code.
而不是10,运行时确定的值可以通过。因为它不是类型操作符新返回的一部分,这是允许的。如果您知道列的数量,但是想要保持行数变量,这很好。typedef使代码更容易阅读。
#2
6
For the sake of completeness, here is a better way to do it in C++ when you know the array bounds ahead of time. The benefit of using the following class is that you don't have to care about calling delete[] on your data. This means that this class will be exception-safe, and all of the other great stuff about RAII.
为了完整起见,这里有一种更好的方法,当您提前知道数组的边界时,使用c++来实现它。使用以下类的好处是,您不必关心调用数据上的delete[]。这意味着这个类将是异常安全的,以及关于RAII的所有其他伟大的东西。
template<typename T, int width, int height>
class MultiArray
{
private:
typedef T cols[height];
cols * data;
public:
T& operator() (int x, int y) { return data[x][y]; }
MultiArray() { data = new cols[width]; }
~MultiArray() { delete [] data; }
};
Usage:
用法:
MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);
edit: and, while I'm at it, here is the setup you can use if you don't know the array bounds until runtime:
编辑:当我在这里的时候,如果你在运行时之前不知道数组的边界,你可以使用以下设置:
template<typename T>
class Array2D
{
private:
const int width;
T * data;
public:
T& operator() (int x, int y) { return data[y*width + x]; }
Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
~Array2D() { delete [] data; }
};
Usage:
用法:
Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
#3
6
How about using Boost.Multiarray ? I believe it answers your need quite well ! http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction
如何使用Boost。Multiarray吗?我相信它能很好地回答你的需要!http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html sec_introduction
Here is an excerpt from the documentation page :
以下是文件页的摘录:
#include < boost/multi_array.hpp >
#include < cassert >
int main ()
{
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array< double, 3 > array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
#4
6
See this: C++ FAQ by Marshall Cline
请参见Marshall Cline的c++ FAQ
See "How do I allocate multidimensional arrays using new?" and "But the previous FAQ’s code is SOOOO tricky and error prone! Isn’t there a simpler way?" sections.
请参见“如何使用new分配多维数组?”和“但是之前的FAQ代码非常棘手,容易出错!”难道没有更简单的方法吗?
#5
3
std::vector<std::vector<int> >
should be mentioned, as it's often the simplest way. However, be aware that it is non-rectangular. Not every std::vector<int>
needs to have the same length.
必须提到向量
<:vector>
>,因为它通常是最简单的方法。但是,要注意它是非矩形的。不是每个std::向量
#6
3
I'm surprised no one has mentioned boost::multi_array
yet. I needed a 2D array in a program just last week, and found it to be a lot easier, and quicker to code, than the home-brewed solutions that I've come up with before (all of which are mentioned in other comments).
我很惊讶没有人提到boost::multi_array。就在上周,我在一个程序中需要一个2D数组,发现它比我以前提出的自制解决方案(所有这些都在其他评论中提到)要容易得多,编码也更快。
#7
3
Here's the implementation I've got; I declare a single contiguous block of int
s instead of creating new blocks inside my for loop, so I'm not causing page faults all over the place. Thanks to eJames for pointing out why this code was broken originally.
这是我得到的实现;我声明一个连续的ints块,而不是在我的for循环中创建新的块,所以我不会在整个地方造成页面错误。感谢eJames指出为什么这个代码最初被破坏。
int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];
for ( int i = 0; i < height; ++i )
{
myArray[i] = data + (i*width);
}
// do some things here
delete[] data;
delete[] myArray;
#8
2
Your loop would not write the pointer values into myArray
properly. I would suggest the following instead:
循环不会正确地将指针值写入myArray中。我建议这样做:
int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
myArray[i] = index;
index += height;
}
// ...
delete[] data;
delete[] myArray;
#9
2
As another alternative, STLSoft includes a fixed_array_2d class (as well as 3D and 4D versions). Compared with the homebrewed solutions given here, it has a similar implementation but a more complete feature set (full support for iterators, etc.). Compared with boost::multi_array, it's lighter weight and easier on not-quite-compliant C++ compilers but (intentionally) lacks some of multi_array's features.
作为另一种选择,STLSoft包含fixed_array_2d类(以及3D和4D版本)。与本文给出的自制解决方案相比,它有一个类似的实现,但是有一个更完整的特性集(完全支持迭代器等)。与boost::multi_array相比,它重量更轻,对于不兼容c++编译器更容易,但(故意)缺少multi_array的一些特性。
#10
0
You can index a one dimensional as a 2, 3, or N dimensional one if you just space over the correct amount of elements. For example, if I've got 10 rows and 10 columns, I know that if I'm on row 3 I will have to go over at least 30 elements to get to it.
如果你只是在正确的元素数量上空间的话,你可以将一维的索引为2 3或N维的1。例如,如果我有10行和10列,我知道如果我在第3行,我需要至少检查30个元素才能得到它。
Somehow I prefer this notation for simple 2D arrays since I don't need to worry about nested levels of pointers. The downside is the messier index notation. Here's an example with a 2D array with n rows and m columns:
由于不需要担心指针的嵌套级别,所以我更喜欢用这种符号表示简单的2D数组。缺点是比较混乱的索引符号。这里有一个带有n行和m列的2D数组的例子:
int *matrix = new int[n*m];
//set element (3,7) to 10
matrix[3*m+7] = 10;
//print the matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << matrix[i*m+j] << ' ';
}
cout << '\n';
}
#11
0
My question here covers mostly the same topic rather well thanks to some superb answers. However, it doesn't cover N-Dimensional arrays, which I haven't seen addressed in the answers here either, but that would be useful.
我的问题几乎涵盖了同样的话题,这要感谢一些精彩的回答。但是,它不涉及n维数组,我在这里的答案中也没有提到,但是这将是有用的。
#12
0
This a reproduction of a post on another thread. It does exactly what you want, without needing to know the array dimensions ahead of time, and without using boost or STL.
这是另一根线上一根柱子的复制品。它所做的正是您想要的,不需要提前知道数组的大小,也不需要使用boost或STL。
Heres a routine which allocates the 3D array of dimension N1 x N2 x N3 in contiguous memory space while allowing you the a[i][j][k] syntax for operator access. The array is dynamic but continuous so it's a huge plus over the vector<> approach and loops of new[] calls.
这里有一个例程,它在连续内存空间中分配维度N1 x N2 x N3的3D数组,同时允许您使用操作符访问的a[i][j][k]语法。数组是动态的,但连续的,所以它比向量<>方法和新的[]调用的循环要大。
template <class T> T ***Create3D(int N1, int N2, int N3)
{
T *** array = new T ** [N1];
array[0] = new T * [N1*N2];
array[0][0] = new T [N1*N2*N3];
int i,j,k;
for( i = 0; i < N1; i++) {
if (i < N1 -1 ) {
array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);
array[i+1] = &(array[0][(i+1)*N2]);
}
for( j = 0; j < N2; j++) {
if (j > 0) array[i][j] = array[i][j-1] + N3;
}
}
cout << endl;
return array;
};
template <class T> void Delete3D(T ***array) {
delete[] array[0][0];
delete[] array[0];
delete[] array;
};
And later in your implementation routine...
在以后的实现例程中……
int *** array3d;
int N1=4, N2=3, N3=2;
int elementNumber = 0;
array3d = Create3D<int>(N1,N2,N3);
//equivalently, a 'flat' array could be obtained with
//int * array = array3d[0][0];
cout << "{" << endl;
for (i=0; i<N1; i++) {
cout << "{";
for (j=0; j<N2; j++) {
cout << "{";
for (k=0; k<N3; k++) {
array3d[i][j][k] = elementNumber++;
cout << setw(4) << array3d[i][j][k] << " ";
//or if you're using the flat array:
//array[i*N2*N3 + j*N3 + k] = elementNumber++;
}
cout << "}";
}
cout << "}";
cout << endl ;
}
cout << "}" << endl;
Delete3D(array3d);
Gives the output:
给出了输出:
{
{{ 0 1 }{ 2 3 }{ 4 5 }}
{{ 6 7 }{ 8 9 }{ 10 11 }}
{{ 12 13 }{ 14 15 }{ 16 17 }}
{{ 18 19 }{ 20 21 }{ 22 23 }}
}
#1
24
If you know the size of nested dimensions already, you can also literally allocate a multi dimensional array using new:
如果您已经知道了嵌套维度的大小,您还可以使用new来分配多维数组:
typedef int dimensions[3][4];
dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;
instead of 10
, a runtime determined value can be passed. Since it's not part of the type operator new returns, that's allowed. This is nice if you know the number of columns, but want to keep the number of rows variable, for example. The typedef makes it easier to read the code.
而不是10,运行时确定的值可以通过。因为它不是类型操作符新返回的一部分,这是允许的。如果您知道列的数量,但是想要保持行数变量,这很好。typedef使代码更容易阅读。
#2
6
For the sake of completeness, here is a better way to do it in C++ when you know the array bounds ahead of time. The benefit of using the following class is that you don't have to care about calling delete[] on your data. This means that this class will be exception-safe, and all of the other great stuff about RAII.
为了完整起见,这里有一种更好的方法,当您提前知道数组的边界时,使用c++来实现它。使用以下类的好处是,您不必关心调用数据上的delete[]。这意味着这个类将是异常安全的,以及关于RAII的所有其他伟大的东西。
template<typename T, int width, int height>
class MultiArray
{
private:
typedef T cols[height];
cols * data;
public:
T& operator() (int x, int y) { return data[x][y]; }
MultiArray() { data = new cols[width]; }
~MultiArray() { delete [] data; }
};
Usage:
用法:
MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);
edit: and, while I'm at it, here is the setup you can use if you don't know the array bounds until runtime:
编辑:当我在这里的时候,如果你在运行时之前不知道数组的边界,你可以使用以下设置:
template<typename T>
class Array2D
{
private:
const int width;
T * data;
public:
T& operator() (int x, int y) { return data[y*width + x]; }
Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
~Array2D() { delete [] data; }
};
Usage:
用法:
Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
#3
6
How about using Boost.Multiarray ? I believe it answers your need quite well ! http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction
如何使用Boost。Multiarray吗?我相信它能很好地回答你的需要!http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html sec_introduction
Here is an excerpt from the documentation page :
以下是文件页的摘录:
#include < boost/multi_array.hpp >
#include < cassert >
int main ()
{
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array< double, 3 > array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
#4
6
See this: C++ FAQ by Marshall Cline
请参见Marshall Cline的c++ FAQ
See "How do I allocate multidimensional arrays using new?" and "But the previous FAQ’s code is SOOOO tricky and error prone! Isn’t there a simpler way?" sections.
请参见“如何使用new分配多维数组?”和“但是之前的FAQ代码非常棘手,容易出错!”难道没有更简单的方法吗?
#5
3
std::vector<std::vector<int> >
should be mentioned, as it's often the simplest way. However, be aware that it is non-rectangular. Not every std::vector<int>
needs to have the same length.
必须提到向量
<:vector>
>,因为它通常是最简单的方法。但是,要注意它是非矩形的。不是每个std::向量
#6
3
I'm surprised no one has mentioned boost::multi_array
yet. I needed a 2D array in a program just last week, and found it to be a lot easier, and quicker to code, than the home-brewed solutions that I've come up with before (all of which are mentioned in other comments).
我很惊讶没有人提到boost::multi_array。就在上周,我在一个程序中需要一个2D数组,发现它比我以前提出的自制解决方案(所有这些都在其他评论中提到)要容易得多,编码也更快。
#7
3
Here's the implementation I've got; I declare a single contiguous block of int
s instead of creating new blocks inside my for loop, so I'm not causing page faults all over the place. Thanks to eJames for pointing out why this code was broken originally.
这是我得到的实现;我声明一个连续的ints块,而不是在我的for循环中创建新的块,所以我不会在整个地方造成页面错误。感谢eJames指出为什么这个代码最初被破坏。
int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];
for ( int i = 0; i < height; ++i )
{
myArray[i] = data + (i*width);
}
// do some things here
delete[] data;
delete[] myArray;
#8
2
Your loop would not write the pointer values into myArray
properly. I would suggest the following instead:
循环不会正确地将指针值写入myArray中。我建议这样做:
int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
myArray[i] = index;
index += height;
}
// ...
delete[] data;
delete[] myArray;
#9
2
As another alternative, STLSoft includes a fixed_array_2d class (as well as 3D and 4D versions). Compared with the homebrewed solutions given here, it has a similar implementation but a more complete feature set (full support for iterators, etc.). Compared with boost::multi_array, it's lighter weight and easier on not-quite-compliant C++ compilers but (intentionally) lacks some of multi_array's features.
作为另一种选择,STLSoft包含fixed_array_2d类(以及3D和4D版本)。与本文给出的自制解决方案相比,它有一个类似的实现,但是有一个更完整的特性集(完全支持迭代器等)。与boost::multi_array相比,它重量更轻,对于不兼容c++编译器更容易,但(故意)缺少multi_array的一些特性。
#10
0
You can index a one dimensional as a 2, 3, or N dimensional one if you just space over the correct amount of elements. For example, if I've got 10 rows and 10 columns, I know that if I'm on row 3 I will have to go over at least 30 elements to get to it.
如果你只是在正确的元素数量上空间的话,你可以将一维的索引为2 3或N维的1。例如,如果我有10行和10列,我知道如果我在第3行,我需要至少检查30个元素才能得到它。
Somehow I prefer this notation for simple 2D arrays since I don't need to worry about nested levels of pointers. The downside is the messier index notation. Here's an example with a 2D array with n rows and m columns:
由于不需要担心指针的嵌套级别,所以我更喜欢用这种符号表示简单的2D数组。缺点是比较混乱的索引符号。这里有一个带有n行和m列的2D数组的例子:
int *matrix = new int[n*m];
//set element (3,7) to 10
matrix[3*m+7] = 10;
//print the matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << matrix[i*m+j] << ' ';
}
cout << '\n';
}
#11
0
My question here covers mostly the same topic rather well thanks to some superb answers. However, it doesn't cover N-Dimensional arrays, which I haven't seen addressed in the answers here either, but that would be useful.
我的问题几乎涵盖了同样的话题,这要感谢一些精彩的回答。但是,它不涉及n维数组,我在这里的答案中也没有提到,但是这将是有用的。
#12
0
This a reproduction of a post on another thread. It does exactly what you want, without needing to know the array dimensions ahead of time, and without using boost or STL.
这是另一根线上一根柱子的复制品。它所做的正是您想要的,不需要提前知道数组的大小,也不需要使用boost或STL。
Heres a routine which allocates the 3D array of dimension N1 x N2 x N3 in contiguous memory space while allowing you the a[i][j][k] syntax for operator access. The array is dynamic but continuous so it's a huge plus over the vector<> approach and loops of new[] calls.
这里有一个例程,它在连续内存空间中分配维度N1 x N2 x N3的3D数组,同时允许您使用操作符访问的a[i][j][k]语法。数组是动态的,但连续的,所以它比向量<>方法和新的[]调用的循环要大。
template <class T> T ***Create3D(int N1, int N2, int N3)
{
T *** array = new T ** [N1];
array[0] = new T * [N1*N2];
array[0][0] = new T [N1*N2*N3];
int i,j,k;
for( i = 0; i < N1; i++) {
if (i < N1 -1 ) {
array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);
array[i+1] = &(array[0][(i+1)*N2]);
}
for( j = 0; j < N2; j++) {
if (j > 0) array[i][j] = array[i][j-1] + N3;
}
}
cout << endl;
return array;
};
template <class T> void Delete3D(T ***array) {
delete[] array[0][0];
delete[] array[0];
delete[] array;
};
And later in your implementation routine...
在以后的实现例程中……
int *** array3d;
int N1=4, N2=3, N3=2;
int elementNumber = 0;
array3d = Create3D<int>(N1,N2,N3);
//equivalently, a 'flat' array could be obtained with
//int * array = array3d[0][0];
cout << "{" << endl;
for (i=0; i<N1; i++) {
cout << "{";
for (j=0; j<N2; j++) {
cout << "{";
for (k=0; k<N3; k++) {
array3d[i][j][k] = elementNumber++;
cout << setw(4) << array3d[i][j][k] << " ";
//or if you're using the flat array:
//array[i*N2*N3 + j*N3 + k] = elementNumber++;
}
cout << "}";
}
cout << "}";
cout << endl ;
}
cout << "}" << endl;
Delete3D(array3d);
Gives the output:
给出了输出:
{
{{ 0 1 }{ 2 3 }{ 4 5 }}
{{ 6 7 }{ 8 9 }{ 10 11 }}
{{ 12 13 }{ 14 15 }{ 16 17 }}
{{ 18 19 }{ 20 21 }{ 22 23 }}
}