关于c ++:Matrix类错误:表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)

Matrix Class Error: Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

这是我第一次使用StackOverflow,很高兴认识大家。我正在编写一个矩阵类,它重载赋值、加法、减法等。赋值运算符"="重载部分似乎工作正常,但如果我试图重载加法"+"运算符,则会收到如下错误消息:

"调试断言失败!程序:…NTSC++Weal6…Wea6Matrx.EXE

文件:f:ddvctoolscrt_bldself_x86crtsrcdbgdel.cpp

线:52

表达式:_block_type_is_valid(phead->nblockuse)"

但是如果我在析构函数中删除了"delete[]matrix",一切都会正常工作,但是由于这个项目的要求,我需要在析构函数中使用这个术语。

我本可以发布一张图片,但这是我第一次使用这个网站,所以我还没有这样做的名声,所以如果我的问题似乎不合理,我道歉,但我会尽力解释它,如果你对我的问题有任何进一步的问题。

谢谢您。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include<iostream>
#include <stdlib.h>
using namespace std;
//dynamic matrix
class dymatrix
{
  friend ostream & operator << (ostream &os, dymatrix &om);
  friend istream & operator >> (istream &is, dymatrix &om);
private:
  int rows;
  int columns;
  double *matrix;
public:

  dymatrix(){cout<<"Default constructor called"<<endl; columns = 0; rows=0; matrix=0;}
  dymatrix(int inrows, int incolumns)
  {
    rows = inrows;
    columns = incolumns;
    matrix = new double [inrows*incolumns];
    for (int i=0; i<inrows*incolumns; i++)
    {
        matrix[i]=0;
    }
  }
  int lengthr() const {return rows;}  //Returns number of rows.
  int lengthc() const {return columns;}   //Return number of columns.
  dymatrix& operator=(dymatrix&);
  ~dymatrix(){cout<<"Destructor called"<<endl;delete[] matrix;}  

  int index(int i, int j)  //This member function returns the position of each index.
  {
    if (j > 0 && j <=rows && i > 0 && i <=columns)
    {
        return (i-1)+(j-1)*columns;
    }
    else {cout<<"Error, out of range"<<endl; exit (1);}
  }
  double & operator()(int i, int j) {return matrix[index(i,j)];}  //The operator () returns the position of j and i in 1D array.

  dymatrix operator + (dymatrix &arr)  //overloading addition.
  {  

    if (rows !=arr.rows && columns != arr.columns)
    {
        cerr<<"SIZE DO NOT MATCH, YOU FAIL"<<endl; exit(1);
    }
    dymatrix new_matrix(rows,columns);
    for (int j = 0; j < arr.rows*arr.columns; j++)
    {
        //for (int i = 1; i <= arr.columns; i++)
        //{
        //cout<<"****"<<j<<endl;    
        new_matrix.matrix[j]= matrix[j]+arr.matrix[j]; //Putting in the data into this dynamic array for each element.
        //}
    }
    return new_matrix;
  }

};  //Class end.
  dymatrix & dymatrix::operator = (dymatrix &arr) //Overloading"=" operator.
  {
    if (&arr == this) return *this; //If the array is the same, no need to change, just to print. The key word"this" is a pointer to the object, and *this gives the object.
    delete[] matrix; matrix =0; rows =0; columns =0;
    rows = arr.rows;   //Setting row length.
    columns = arr.columns;    //Setting column length.
    if(rows*columns > 0)
    {
        matrix = new double [rows*columns]; //Defining a dynamic array here.
        for (int j = 1; j <= rows; j++) //Assigning each term to each term.
        {
            for (int i =1; i <=columns;i++ )
            {
            matrix[index(i,j)] = arr(i,j);  //This is the assigning part, the loop above loops everything so that each term is assigned.
            }
        }
    }
    return *this;   //Return
  }

  istream & operator >> (istream &is, dymatrix &om)   //Overloading">>" operator here to
  {
    cout<<"Please enter the number of rows you want"<<endl;
    is >> om.rows;  //Inputting number of rows.
    cout<<"Enter the number of columns you want"<<endl;
    is >> om.columns;   //Inputting number of columns.
    cout<<"Enter matrix"<<endl;
    om.matrix = new double [om.rows*om.columns];    //Making a dynamic array here to put the data in.
    for (int j = 1; j <= om.rows; j++)
    {
        for (int i = 1; i <= om.columns; i++)
        {
            is >> om.matrix[om.index(i,j)]; //Putting in the data into this dynamic array for each element.
        }
    }
    return is;
  }
  ostream & operator << (ostream &os,   dymatrix &om)  //To output the matrix in an standard matrix way
  {
    for(int j= 1; j<=om.rows; j++)
    {
        os<<endl<<endl;
        for (int i = 1; i <=om.columns;i++)
        {
            os << om.matrix[om.index(i,j)]<<"\t";   //Similar method used in istream.
        }
    }
    return os;
  }
int main()
{
  dymatrix a1;
  cin >> a1;  //Define the rows of the matrix
  cout << a1<<endl<<endl;
  dymatrix a2;
  cin >> a2;
  cout << a2<<endl<<endl;
  dymatrix resu_a1;
  resu_a1=a1+a2;
  cout<<"Addition ="<<resu_a1<<endl;
  dymatrix resu_a3;
  resu_a3 = a1;
  cout<<"Assigning ="<<resu_a3<<endl;
  return 0;
}

这是我的毁灭者:

1
~dymatrix(){cout<<"Destructor called"<<endl;delete[] matrix;}

这是当我重载赋值"="运算符(类外)时,它似乎起作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dymatrix & dymatrix::operator = (dymatrix &arr) //Overloading"=" operator.
  {
    if (&arr == this) return *this; //If the array is the same, no need to change, just to print. The key word"this" is a pointer to the object, and *this gives the object.
    delete[] matrix; matrix =0; rows =0; columns =0;
    rows = arr.rows;   //Setting row length.
    columns = arr.columns;    //Setting column length.
    if(rows*columns > 0)
    {
        matrix = new double [rows*columns]; //Defining a dynamic array here.
        for (int j = 1; j <= rows; j++) //Assigning each term to each term.
        {
            for (int i =1; i <=columns;i++ )
            {
            matrix[index(i,j)] = arr(i,j);  //This is the assigning part, the loop above loops everything so that each term is assigned.
            }
        }
    }
    return *this;   //Return
  }

但是当我在类中重载加法运算符"+"时,我会得到上面引用的错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dymatrix operator + (dymatrix &arr)  //overloading addition.
{  

    if (rows !=arr.rows && columns != arr.columns)
    {
        cerr<<"SIZE DO NOT MATCH, YOU FAIL"<<endl; exit(1);
    }
    dymatrix new_matrix(rows,columns);
    for (int j = 0; j < arr.rows*arr.columns; j++)
    {
        //for (int i = 1; i <= arr.columns; i++)
        //{
        //cout<<"****"<<j<<endl;    
        new_matrix.matrix[j]= matrix[j]+arr.matrix[j]; //Putting in the data into this dynamic array for each element.
        //}
    }
    return new_matrix;
}

这是我的内景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
  dymatrix a1;
  cin >> a1;  //Define the rows of the matrix
  cout << a1<<endl<<endl;
  dymatrix a2;
  cin >> a2;
  cout << a2<<endl<<endl;
  dymatrix resu_a1;
  resu_a1=a1+a2;
  cout<<"Addition ="<<resu_a1<<endl;
  dymatrix resu_a3;
  resu_a3 = a1;
  cout<<"Assigning ="<<resu_a3<<endl;
return 0;
}


当您调用operator +时,您正在返回矩阵的副本,但是您的dymatrix缺少用户定义的复制构造函数:

1
dymatrix(const dymatrix&);  // this is the missing function

您必须实现此函数,使您的dymatrix的返回值正确。如果没有这个函数,您的代码将表现出未定义的行为,并且在对象破坏(双重删除错误和/或内存泄漏)的时候很可能崩溃。

查看"3法则"。如果实现了用户定义的赋值运算符,则还应实现用户定义的复制构造函数和析构函数:

三个规则是什么?

最简单的方法是将大部分(如果不是全部)代码从您的operator=移到复制构造函数。然后根据复制构造函数使用copy/swap惯用法实现operator=

什么是复制和交换习语?

至于您对operator=的实现:为什么要做所有这些工作来从一个数组复制到另一个数组?它应该是一个直的循环,从0到rows*columns。您不需要调用所有这些外部函数来获取index等。

但是回到复制构造函数,它很可能看起来像这样:

1
2
3
4
5
6
7
8
#include
//...
dymatrix::dymatrix(const dymatrix& arr) :
        rows(arr.rows), columns(arr.columns),
        matrix(new double[arr.rows * arr.columns])
{
   std::copy(arr.matrix, arr.matrix + rows*columns, matrix);
}

现在,您的分配操作员可以这样编码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include
//...
class dymatrix {
   //...
    dymatrix& operator=(dymatrix arr); // use this version of assignment operator
  //...
};

//...
dymatrix& dymatrix::operator=(dymatrix arr)  
{
   std::swap(rows, arr.rows);
   std::swap(columns, arr.columns);
   std::swap(matrix, arr.matrix);
   return *this;
}

另一点是,在实施operator +之前,您应该先实现operator+=。原因是,您可以根据operator +=编写operator +,从而创建两个运算符,其中operator +本质上是一个3行函数(当前operator +中的代码将移动到operator +=

另一点是,你的operator+应该通过const dymatrix&,而不是dymatrix&。您没有在函数中更改参数,因此它应该作为const引用传递。

最后一点是,如果在添加矩阵时矩阵的大小不同,那么代码应该抛出一个异常——它不应该像代码那样退出程序,尤其是不在类中。

这可以解释为什么你永远不应该这样做(我知道这可能是学校的练习,但这样做太糟糕了):

exit()在应返回引用的函数内调用