1

3次元配列の次のクラスを作成しました。たとえば、変数を宣言する

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);解放する割り当て演算子がないため、 NULL ポインターでアクセスG[i][j][k]しています。operator()

于 2013-01-20T22:00:40.377 に答える
2

メモリを動的に割り当てましたが、3 つのルールに従っていません。代入演算子がないため、これを行うと:

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.

n2行目で割り当てに使用された一時メモリと同じメモリを指すポインターがあるため、同じメモリの割り当て解除が2回試行されます。一時的に死ぬと、メモリの割り当てが解除されます。死ぬとn、同じメモリの割り当てを解除しようとします。さらに、2行目以降のそのメモリへのアクセスは未定義の動作です。

于 2013-01-20T22:05:35.893 に答える