指针数组的动态 allocation/deallocation
Dynamic allocation/deallocation of array of pointers
Via Whosebug threads like this one,我发现你可以使用指针数组来管理二维数组。以前我用指针指向指针来存储二维数组,但现在我需要将我的数据存储在连续的内存中,所以指针指向指针格式不再起作用。
原始二维数组是指针数组的替代方法,但原始二维数组对我不起作用,因为我希望能够在堆中而不是堆栈中分配存储空间,因为我的容器可以非常很大,如果我使用原始二维数组,我可能会遇到堆栈溢出。
我的问题是关于如何为指针数组分配内存。我使用如下所示的 new
运算符(请参阅我的构造函数)来分配我的指针数组
#include <iostream>
using namespace std;
template<typename DataType, unsigned numRows, unsigned numCols>
class Container2D {
public:
Container2D() {
m_data = new DataType[numRows][numCols];
}
~Container2D() {
delete [] m_data;
}
DataType* getData() { return &m_data[0][0]; }
private:
DataType (*m_data)[numCols];
};
int main() {
Container2D<int, 3, 3> container;
return 0;
}
是new DataType[numRows][numCols]
在堆上分配整个二维数组还是在堆上分配numRows
指针,同时在堆栈上分配numCols
个DataType类型的对象?
在指向指针的场景中(我将我的存储定义为 DataType** m_data
),我知道我的数组的两个维度都分配在堆上,我会调用 delete m_data[i]
为每一列,然后调用 delete[] m_data
来释放我的行数据。在指针数组场景中,我不确定我上面的析构函数是否正确释放数据。
一种方法是使用一维连续数组并实现二维索引到一维索引的映射:
#include <iostream>
#include <cassert>
using namespace std;
template<typename DataType, unsigned numRows, unsigned numCols>
class Container2D {
public:
Container2D() { m_data = new DataType[numRows * numCols]; }
~Container2D() { delete [] m_data; }
inline DataType operator()(unsigned i, unsigned j) const {
assert( 0 <= i && i < numRows);
assert( 0 <= j && j < numCols);
return m_data[i*numCols+j];
}
inline DataType& operator()(unsigned i, unsigned j) {
// same as above, but this allows inplace modifications
assert( 0 <= i && i < numRows);
assert( 0 <= j && j < numCols);
return m_data[i*numCols+j];
}
private:
DataType* m_data;
};
int main() {
Container2D<int, 3, 3> container;
int x = container(0,0); // retrieve the element at (0,0);
container(1,2) = 9; // modify the element at (1,2);
// int y = container(3,0); // triggers assertion errors for out-of-bound indexing
return 0;
}
备注:
- 如果
numRows
和 numCols
没有针对特定的 class 实例更改,则在这种情况下不需要 new
和 delete
。如果它们确实动态变化,最好将它们存储为成员变量而不是模板参数。如果 numRows
和 numCols
太大,可以动态分配 Container2D
个对象作为一个整体。
- 正如@GoswinvonBrederlow 评论的那样,这与
new m_data[numRows][numCols]
在内存布局方面没有区别,但这种约定使得扩展到更高维度变得更容易。
Does new DataType[numRows][numCols] allocate the entire 2D array on the heap or does it allocate numRows pointers on the heap while allocating numCols objects of type DataType on the stack?
写的时候
DataType arr[numRows][numCols];
如您所述,内存将位于一个连续块中。使用 new
时没有任何变化。它将分配一个连续的指定类型的内存块。没有隐藏的指向真实数据的指针数组。
Via Whosebug threads like this one,我发现你可以使用指针数组来管理二维数组。以前我用指针指向指针来存储二维数组,但现在我需要将我的数据存储在连续的内存中,所以指针指向指针格式不再起作用。
原始二维数组是指针数组的替代方法,但原始二维数组对我不起作用,因为我希望能够在堆中而不是堆栈中分配存储空间,因为我的容器可以非常很大,如果我使用原始二维数组,我可能会遇到堆栈溢出。
我的问题是关于如何为指针数组分配内存。我使用如下所示的 new
运算符(请参阅我的构造函数)来分配我的指针数组
#include <iostream>
using namespace std;
template<typename DataType, unsigned numRows, unsigned numCols>
class Container2D {
public:
Container2D() {
m_data = new DataType[numRows][numCols];
}
~Container2D() {
delete [] m_data;
}
DataType* getData() { return &m_data[0][0]; }
private:
DataType (*m_data)[numCols];
};
int main() {
Container2D<int, 3, 3> container;
return 0;
}
是new DataType[numRows][numCols]
在堆上分配整个二维数组还是在堆上分配numRows
指针,同时在堆栈上分配numCols
个DataType类型的对象?
在指向指针的场景中(我将我的存储定义为 DataType** m_data
),我知道我的数组的两个维度都分配在堆上,我会调用 delete m_data[i]
为每一列,然后调用 delete[] m_data
来释放我的行数据。在指针数组场景中,我不确定我上面的析构函数是否正确释放数据。
一种方法是使用一维连续数组并实现二维索引到一维索引的映射:
#include <iostream>
#include <cassert>
using namespace std;
template<typename DataType, unsigned numRows, unsigned numCols>
class Container2D {
public:
Container2D() { m_data = new DataType[numRows * numCols]; }
~Container2D() { delete [] m_data; }
inline DataType operator()(unsigned i, unsigned j) const {
assert( 0 <= i && i < numRows);
assert( 0 <= j && j < numCols);
return m_data[i*numCols+j];
}
inline DataType& operator()(unsigned i, unsigned j) {
// same as above, but this allows inplace modifications
assert( 0 <= i && i < numRows);
assert( 0 <= j && j < numCols);
return m_data[i*numCols+j];
}
private:
DataType* m_data;
};
int main() {
Container2D<int, 3, 3> container;
int x = container(0,0); // retrieve the element at (0,0);
container(1,2) = 9; // modify the element at (1,2);
// int y = container(3,0); // triggers assertion errors for out-of-bound indexing
return 0;
}
备注:
- 如果
numRows
和numCols
没有针对特定的 class 实例更改,则在这种情况下不需要new
和delete
。如果它们确实动态变化,最好将它们存储为成员变量而不是模板参数。如果numRows
和numCols
太大,可以动态分配Container2D
个对象作为一个整体。 - 正如@GoswinvonBrederlow 评论的那样,这与
new m_data[numRows][numCols]
在内存布局方面没有区别,但这种约定使得扩展到更高维度变得更容易。
Does new DataType[numRows][numCols] allocate the entire 2D array on the heap or does it allocate numRows pointers on the heap while allocating numCols objects of type DataType on the stack?
写的时候
DataType arr[numRows][numCols];
如您所述,内存将位于一个连续块中。使用 new
时没有任何变化。它将分配一个连续的指定类型的内存块。没有隐藏的指向真实数据的指针数组。