复制动态二维数组的构造函数

时间:2015-10-28 14:14:42

标签: c++ class copy-constructor

我需要帮助。现在我正在尝试创建一个类Matrix,但每次在Visual Studio 2013中运行它时我的程序都会冻结。我认为复制构造函数存在一些问题。这是整个代码。 `

class Matrix
{
private:
    int** matrix;
    int X; // Matrix rows
    int Y; // Matrix columns
public:
    // Default Constructor
    Matrix()
    {
        X = 0;
        Y = 0;
        matrix = NULL;
    }
    // Constructor with parameters
    Matrix(int _X, int _Y)
    {
        srand(time(NULL));

        X = _X;
        Y = _Y;
        matrix = new int*[X];

        for (int i = 0; i < X; i++)
                matrix[i] = new int[Y];

        for (int i = 0; i < X; i++)
        {
            for (int j = 0; j < Y; j++)
            {
                matrix[i][j] = rand() % 100;
            }
        }

    }
    // Copy constructor
    Matrix(const Matrix& N)
    {
        X = N.X;
        Y = N.Y;

        matrix = new int*[X];

        for (int i = 0; i < X; i++)
            matrix[i] = new int[Y];

        for (int i = 0; i < X; i++)
        {
            for (int j = 0; j < Y; j++)
            {
                matrix[i][j] = N.matrix[i][j];
            }
        }
    }
    // Destructor
    ~Matrix()
    {
        for (int i = 0; i < X; i++)
            delete[] matrix[X];
    }
    //--------------------------------------
    void ShowMatrixOnScreen()
    {
        for (int i = 0; i < X; i++)
        {
            for (int j = 0; j < Y; j++)
                cout << matrix[i][j] << "   ";

            cout << endl << endl;
        }
    }
};

void main() 
{
    Matrix x(4, 2);
    x.ShowMatrixOnScreen();
}

`

功能&#34; ShowMatrixOnScreen&#34;打印矩阵&#34; x&#34;在屏幕上,然后控制台冻结。

2 个答案:

答案 0 :(得分:7)

你的析构函数有声明 Template.myTemplate.events({ 'click #btnEditPhoto': function(event, template) { $('.profilePhotoFile').click(); }, 'change .profilePhotoFile': function(event, template) { if (!event.target.files || event.target.files.length === 0) { return; } else { var $inputImage = $(event.target); var URL = window.URL || window.webkitURL; var file = event.target.files[0]; var blobURL = URL.createObjectURL(file); $image = $('#cropper > img'); $('#cropper-modal').modal(); $('#cropper-modal').on('shown.bs.modal', function() { $image.cropper({ aspectRatio: 1.0, autoCropArea: 1.0 }).cropper('replace', blobURL); $inputImage.val(''); }).on('hidden.bs.modal', function() { $image.cropper('destroy'); URL.revokeObjectURL(blobURL); // Revoke url }); } }, 'click #btnSavePhoto': function(event, template) { $image = $('#cropper > img'); //Change the width and height to your desired size var base64EncodedImage = $image.cropper('getCroppedCanvas', {width: 10, height: 10}).toDataURL('image/jpeg'); $('#cropper-modal').modal('hide'); var newImage = new FS.File(base64EncodedImage); Images.insert(newImage, function(err, fileObj) { if (err) { console.log(err); } else { //do something after insert } }); }, 'click #btnCancel': function(event, template) { $('#cropper-modal').modal('hide'); } });

delete[] matrix[X];不存在,因此您释放未分配给您的内存,即未定义的行为。它应该是matrix[X]

此外,正如Vlad From Moscow所指出的那样,delete [] matrix[i]所有内存都是可取的,所以你还应该考虑添加delete来删除你分配的1-D指针数组delete [] matrix

答案 1 :(得分:2)

问题是您的析构函数无效

首先在这个循环中

    for (int i = 0; i < X; i++)
        delete[] matrix[X];

它尝试访问分配的数组之外的不存在的元素matrix[X]。索引的有效范围是[0, X - 1]

所以你必须写

    for (int i = 0; i < X; i++)
        delete[] matrix[i];
                       ^^^

但仅当matrix不等于nullptr时,thsi循环才有效。因此,在循环之前,您必须检查matrix是否等于nullptr或不等于delete [] matrix;

还需要删除分配给第一个一维数组的内存

~Matrix()
{
    if ( matrix )
    {
        for ( int i = 0; i < X; i++ ) delete []matrix[i];
    }

    delete []matrix;
}

因此析构函数看起来像

matrix

同样在复制构造函数中,您还应检查复制对象的数据成员nullptr是否也不等于// Copy constructor Matrix(const Matrix& N) { X = N.X; Y = N.Y; if ( N.matrix ) { matrix = new int*[X]; for (int i = 0; i < X; i++) matrix[i] = new int[Y]; for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { matrix[i][j] = N.matrix[i][j]; } } } }

X

如果数据成员Ysize_t的类型为int ** allocate( size_t m, size_t n ) { int **p = nullptr; if ( n != 0 && m != 0 ) { matrix = new int *[m]; for ( size_t i = 0; i < m; i++ ) matrix[i] = new int[n]; } return p; } ,情况会好得多。否则你还需要检查它们是否是否定的。

内存的分配可以放在一个单独的私有成员函数中。

例如

X

在类定义数据中,成员Yprivate: int X; // Matrix rows int Y; // Matrix columns int** matrix; 应位于数据成员矩阵之前

// Constructor with parameters
Matrix(int X, int Y) : X( X ), Y( Y ), matrix( allocate( X, Y ) )
{
   if ( matrix )
   {
       srand(time(NULL));

        for (int i = 0; i < X; i++)
        {
            for (int j = 0; j < Y; j++)
            {
                matrix[i][j] = rand() % 100;
            }
        }
    }
}

在这种情况下,您可以使用mem-initializer构造函数列表来初始化类数据成员。

例如

// Default Constructor
Matrix() : Matrix( 0, 0 )
{
}

默认构造函数可以定义为

// Copy constructor
Matrix( const Matrix &N ) : X( N.X ), Y( N.Y ), matrix( allocate( N.X, N.Y ) )
{
    if ( matrix )
    {
        for (int i = 0; i < X; i++)
        {
            for (int j = 0; j < Y; j++)
            {
                matrix[i][j] = N.matrix[i][j];
            }
        }
    }
}

反过来,复制构造函数可以定义为

int

您还应该定义复制赋值运算符或将其定义为已删除。 否则,当您尝试将该类的一个对象分配给另一个对象时会出现问题。

考虑到函数main应具有返回类型int

{{1}} main()