C++ 正确释放具有底层连续内存的多维数组
C++ Properly deallocate multidimensional array with underlying contiguous memory
我有一个为 3d 数组分配内存的函数。目标是保证内存连续,但也有 a[k][j][i]
语法的便利:
double *** allocate_3d(const int& sz, const int& sy, const int& sx){
double * aMem = new double[sz*sy*sx];
double *** array = new double**[sz];
for(int k=0; k<sz; k++){
array[k] = new double*[sy];
for(int j=0; j<sy; j++){
array[k][j]= aMem + k*sy*sx + j*sx;
}
}
return array;
}
假设我这样调用函数
x = allocate_3d(wdz,wdy,wdx);
我怎样才能正确解除分配 x?我尝试了以下方法:
void delete_3d(double *** array, const int& sz, const int& sy, const int& sx){
for(int k=0; k<sz; k++){
for(int j=0; j<sy; j++){
delete[] array[k][j];
}
delete[] array[k];
}
delete[] array;
}
但是运行 Valgrind 给出了一个错误,似乎表明内存没有正确释放。
其实应该是这样的:
void delete_3d(double *** array, const int& sz, const int& sy, const int& sx) {
// first, restore the pointer to the actual aMem
double * aMem = array[0][0];
// only one dimension was allocated in the loop,
// so only one loop should be deallocating things
for(int k = 0; k < sz; k++) {
delete [] array[k];
}
delete[] array;
delete[] aMem;
}
更好的解决方案
包装 std::vector
以同时获得:连续内存和相当简单的访问语法,并且作为奖励没有额外的数组,这对内存、性能和维护更好:
class Array3d {
public:
Array3d(size_t sx, size_t sy, size_t sz)
: m_sx(sx), m_sy(sy) {
m_array.resize(sx * sy * sz);
}
// Can't overload operator[] with more that one parameter
// so we'll have to do with operator()
double &operator()(size_t x, size_t y, size_t z) {
size_t index = x * m_sx * m_sy + y * m_sy + z;
return m_array[index];
}
private:
size_t m_sx, m_sy;
std::vector<double> m_array;
};
用法示例:
Array3d array(3, 3, 3);
array(0, 1, 2) = 3.14;
我有一个为 3d 数组分配内存的函数。目标是保证内存连续,但也有 a[k][j][i]
语法的便利:
double *** allocate_3d(const int& sz, const int& sy, const int& sx){
double * aMem = new double[sz*sy*sx];
double *** array = new double**[sz];
for(int k=0; k<sz; k++){
array[k] = new double*[sy];
for(int j=0; j<sy; j++){
array[k][j]= aMem + k*sy*sx + j*sx;
}
}
return array;
}
假设我这样调用函数
x = allocate_3d(wdz,wdy,wdx);
我怎样才能正确解除分配 x?我尝试了以下方法:
void delete_3d(double *** array, const int& sz, const int& sy, const int& sx){
for(int k=0; k<sz; k++){
for(int j=0; j<sy; j++){
delete[] array[k][j];
}
delete[] array[k];
}
delete[] array;
}
但是运行 Valgrind 给出了一个错误,似乎表明内存没有正确释放。
其实应该是这样的:
void delete_3d(double *** array, const int& sz, const int& sy, const int& sx) {
// first, restore the pointer to the actual aMem
double * aMem = array[0][0];
// only one dimension was allocated in the loop,
// so only one loop should be deallocating things
for(int k = 0; k < sz; k++) {
delete [] array[k];
}
delete[] array;
delete[] aMem;
}
更好的解决方案
包装 std::vector
以同时获得:连续内存和相当简单的访问语法,并且作为奖励没有额外的数组,这对内存、性能和维护更好:
class Array3d {
public:
Array3d(size_t sx, size_t sy, size_t sz)
: m_sx(sx), m_sy(sy) {
m_array.resize(sx * sy * sz);
}
// Can't overload operator[] with more that one parameter
// so we'll have to do with operator()
double &operator()(size_t x, size_t y, size_t z) {
size_t index = x * m_sx * m_sy + y * m_sy + z;
return m_array[index];
}
private:
size_t m_sx, m_sy;
std::vector<double> m_array;
};
用法示例:
Array3d array(3, 3, 3);
array(0, 1, 2) = 3.14;