动态3d数组的声明和赋值

Declaration and assignation of dynamic 3d array

本文关键字:赋值 声明 3d 数组 动态      更新时间:2023-10-16

我已经为3d数组制作了下一个类。将变量声明为,例如

Grid3d n = Grid3d(2,2,2);
n(0,0,0) = 1;

可以工作,但是声明为

Grid3d n;
n = Grid3d(2,2,2);
n(0,0,0) = 1;

给我一个分割错误,问题似乎是默认构造函数,但我不知道如何修复它,任何线索?

#ifndef _GRID3D_
#define _GRID3D_
#include <iostream>
#include <cmath>
#include <cassert>  // assert()
using namespace std;
class Grid3d
{
private:
    int L;
    int M;
    int N;
    double *** G;
public:
    Grid3d(int,int,int);
    Grid3d();
    Grid3d(const Grid3d &);
    ~Grid3d();
    double & operator()(int,int,int);
};
#endif
//Constructor
Grid3d::Grid3d(int L,int M,int N)
    :L(L), M(M), N(N)
{
    int i,j,k;
    G = new double ** [L];
    for (i=0;i<L;i++){
        G[i] = new double * [M];
        for (j=0;j<M;j++){
            G[i][j] = new double [N];
            for (k=0;k<N;k++){
                G[i][j][k] = 0;
            }
        }
    }
}
//Constructor vacío
Grid3d::Grid3d()
    :L(0), M(0), N(0)
{
    G = NULL;
}
//Constructor copia
Grid3d::Grid3d(const Grid3d &A)
    :L(A.L), M(A.M), N(A.N)
{
    G = new double ** [L];
    int i,j,k;
    for (i=0;i<L;i++){
        G[i] = new double * [M];
        for (j=0;j<M;i++){
            G[i][j] = new double [N];
            for (k=0;k<N;k++){
                G[i][j][k] = A.G[i][j][k];
            }
        }
    }
}
//Destructor
Grid3d::~Grid3d()
{
    // Libera memoria
    for (int i=0;i<L;i++){
        for (int j=0;j<M;j++){
            delete [] G[i][j];
            G[i][j] = NULL;
        }
        delete [] G[i];
        G[i] = NULL;
    }
    delete G;
    G = NULL;
}
double& Grid3d::operator()(int i,int j,int k)
{
    assert(i >= 0 && i < L);
    assert(j >= 0 && j < M);
    assert(k >= 0 && k < N);
    return G[i][j][k];
}
赋值操作符

Grid3d Grid3d::operator = (const Grid3d &A)
{
    if (this == &A) {return *this;};
    if (G != NULL){
        // Libera memoria
        for (int i=0;i<L;i++){
            for (int j=0;j<M;j++){
                delete [] G[i][j];
                G[i][j] = NULL;
            }
            delete [] G[i];
            G[i] = NULL;
        }
        delete G;
        G = NULL;
    }
    L = A.L;
    M = A.M;
    N = A.N;
    G = new double ** [L];
    int i,j,k;
    for (i=0;i<L;i++){
        G[i] = new double * [M];
        for (j=0;j<M;i++){
            G[i][j] = new double [N];
            for (k=0;k<N;k++){
                G[i][j][k] = A.G[i][j][k];
            }
        }
    }
    return *this;
}

您已经动态分配了内存,但是您没有遵循三的规则。您缺少一个赋值操作符,所以当您这样做时:

Grid3d n;
n = Grid3d(2,2,2); // both RHS temporary and n point to the same data.
n(0,0,0) = 1;      // Accessing deleted memory: undefined behaviour.

您将有两次尝试取消分配相同的内存,因为您有n的指针指向与第二行中用于分配它的临时内存相同的内存。当临时终止时,它会重新分配内存。当n死亡时,它会尝试重新分配相同的内存。此外,在第二行之后对该内存的任何访问都是未定义的行为。

这是一个微不足道的打字错误。我来指出这行,并让您指出错误的地方:

for (j=0;j<M;i++)

也就是说,除了缺少赋值操作符,它使n = Grid3d(2,2,2);中的原始构造对象被释放,因此您正在使用NULL指针访问operator()中的G[i][j][k]