C++中的移动分配出现问题.非法指令: 4.

Problem with move assignment in C++. Illegal instruction: 4

本文关键字:非法 问题 指令 移动 分配 C++      更新时间:2023-10-16

我正在编写一个简单的矩阵类,并且我已经定义了运算符+重载和移动赋值。 看起来他们两个互动时发生了一些事情,但我找不到我错在哪里。 这是我的代码(我已经删除了所有多余的内容,只留下了显示错误所需的内容(。 有问题的行在最后,主要是:

#include <iostream>
#define DEF -1
using namespace std;
//----- Matrix -----//
class Matrix{
private:
float **matrixpp;
int dim_r;
int dim_c;
public:
Matrix(int d_r = DEF, int d_c = 0);   
Matrix(const Matrix&);
Matrix(Matrix&&);
Matrix& operator=(Matrix&&);
~Matrix();
Matrix operator+(const Matrix&);
void print();
void fill();
};
//----- Matrix -----//
Matrix::Matrix(int d_r, int d_c){
if(d_r == DEF){
do{
cout << "number of rows: ";
cin >> dim_r;
if(dim_r <= 0){
cout << "ERROR" << endl;
}
}
while(dim_r <= 0);
do{
cout << "Number of columns: ";
cin >> dim_c;
if(dim_c <= 0){
cout << "ERROR" << endl;
}
}
while(dim_c <= 0);

}
else{
dim_r = d_r;
dim_c = d_c;
}
matrixpp = new float*[dim_r];
for(int i = 0; i < dim_r; i++){
matrixpp[i] = new float[dim_c];
}
for(int r = 0; r < dim_r; r++){
for(int c = 0; c < dim_c; c++){
matrixpp[r][c] = 0;
}
}
}
Matrix::Matrix(const Matrix& tocopy)
:matrixpp(tocopy.matrixpp), dim_r(tocopy.dim_r), dim_c(tocopy.dim_c)
{
matrixpp = new float*[dim_r];
for(int i = 0; i < dim_r; i++){
matrixpp[i] = new float[dim_c];
}
for(int r = 0; r < dim_r; r++){
for(int c = 0; c < dim_c; c++){
matrixpp[r][c] = tocopy.matrixpp[r][c];
}
}
}
Matrix::Matrix(Matrix&& tomove)
:matrixpp(tomove.matrixpp), dim_r(tomove.dim_r), dim_c(tomove.dim_c)
{
tomove.matrixpp = nullptr;
}
Matrix& Matrix::operator=(Matrix&& tomove){
cout << "--- MA ---" << endl;
matrixpp = tomove.matrixpp;
dim_r = tomove.dim_r;
dim_c = tomove.dim_c;
tomove.matrixpp = nullptr;
}
Matrix::~Matrix(){
if(matrixpp != nullptr){
for(int i = 0; i < dim_r; i++){
delete[] matrixpp[i];
}
delete[] matrixpp;
}
}
Matrix Matrix::operator+(const Matrix& m){
if(this->dim_r == m.dim_r && this->dim_c == m.dim_c){
Matrix new_m(m.dim_r, m.dim_c);
for(int r = 0; r < new_m.dim_r; r++){
for(int c = 0; c < new_m.dim_c; c++){
new_m.matrixpp[r][c] = this->matrixpp[r][c] + m.matrixpp[r][c];
}
}
return new_m;
}
else{
cout << "ERROR" << endl;
}
}
void Matrix::print(){
int temp;
for(int r = 0; r < dim_r; r++){
for(int c = 0; c < dim_c; c++){
cout << matrixpp[r][c] << " ";
}
cout << endl;
}
cout << endl;
}
void Matrix::fill(){
float temp;
for(int r = 0; r < dim_r; r++){
for(int c = 0; c < dim_c; c++){
cout << "new value: " << endl;
this->print();
cin >> temp;
matrixpp[r][c] = temp;
system("clear");
}
}
}
//-------- Main -------//
int main(){
Matrix m0;
m0.fill();
Matrix m1(0);
m1 = m0+m0; // problematic line
//m1.print();
}

当调用移动分配以在 m00 中移动 m1+m0 的结果时,它会给我错误。

如果我在 Mac 上使用 g++ 编译我的代码,给出的错误只是"非法指令:4",仅此而已。 如果我在 Linux 上执行此操作,给出的错误是:

在成员函数 'Matrix Matrix::operator+(const Matrix&(' 中: P.cpp:90:16:错误:使用已删除的函数"constexpr" Matrix::Matrix(const Matrix&(' 返回new_m; ^~~~~ p.cpp:9:7:注意:"constexpr Matrix::Matrix(const Matrix&("被隐式声明为已删除,因为"Matrix"声明 移动构造函数或移动赋值运算符类矩阵{ ^~~~~~

提前谢谢你!

问题是,当使用 pre-C++17 标准时,没有复制 elision 保证,因此从函数返回值遵循复制初始化语义,这需要定义移动或复制构造函数。定义自己的移动赋值运算符将禁用自动构造函数生成(类副本 CTOR 生成规则(。事实上,编译器提供的构造函数已定义,但已删除。要解决此问题,您必须根据五法则(三/五/零法则(定义一个移动或复制构造函数,或两者兼而有之。

另外,我怀疑原始问题(非法指令(是由代码中的许多未定义行为引起的(例如,赋值运算符中没有返回语句,运算符+ else分支中没有返回(。

主要问题是你的运算符=没有任何回报。

重载运算符 + 像这样:

Matrix operator+(const Matrix &A ,const Matrix &m)
{
if(A->dim_r == m.dim_r && A->dim_c == m.dim_c){
Matrix new_m(m.dim_r, m.dim_c);
for(int r = 0; r < new_m.dim_r; r++){
for(int c = 0; c < new_m.dim_c; c++){
new_m.matrixpp[r][c] = A->matrixpp[r][c] + m.matrixpp[r][c];
}
}
return new_m;
}
else{
cout << "ERROR" << endl;
}

并让它成为你班级的朋友。 在运算符的末尾 = 添加这样的返回语句:

Matrix& Matrix::operator=(Matrix&& tomove){
if(this != &tomove) { 
cout << "--- MA ---" << endl;
matrixpp = tomove.matrixpp;
dim_r = tomove.dim_r;
dim_c = tomove.dim_c;
tomove.matrixpp = nullptr;
}
return *this;
}