1

我已经为 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;
}
4

2 回答 2

2

这是一个微不足道的错字。我会指出这条线,我会让你发现哪里出了问题:

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

也就是说,除了丢失的赋值运算符之外,它n = Grid3d(2,2,2);会释放原始构造的对象,因此您正在使用G[i][j][k]NULLoperator()指针进行访问。

于 2013-01-20T22:00:40.377 回答
2

您已经动态分配了内存,但您没有遵循三的规则。您缺少赋值运算符,因此当您执行此操作时:

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死亡时,它会尝试取消分配相同的内存。此外,在第二行之后对该内存的任何访问都是未定义的行为。

于 2013-01-20T22:05:35.893 回答