模板矩阵类拷贝构造器未处理异常问题求助
模板矩阵类的未处理异常问题分析与修复
遇到的错误:
未处理异常: 0x00007FF60FEC7836 (hw2.exe): 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问违规。
核心问题:运算符*返回局部对象的引用
先看这段运算符重载代码:
template<int Rows, int Cols, class T = int> Matrix<Rows, Cols>& operator*(int n, const Matrix<Rows, Cols>& mat) { Matrix<Rows, Cols> temp; for (int i = 0;i < Rows;i++) { for (int j = 0;j < Cols;j++) { std::cout << "in the * operator" << std::endl; temp.data[i][j] = mat.data[i][j] * n; } } return temp; }
函数内的temp是局部栈对象,当函数执行完毕时,temp会被销毁,其占用的内存会被系统回收。此时返回temp的引用,得到的是一个悬空引用——指向已经被释放的内存空间。后续代码访问这个引用时,就会触发内存访问违规错误。
注意:返回值完全可以支持链式操作(比如(mat +2)*3),不需要返回引用。临时对象的返回会被编译器优化(RVO/NRVO),不会有性能问题。
拷贝构造器的错误实现
拷贝构造器中的两处NULL检查完全错误且多余:
Matrix(const Matrix& other) { if (other.data == NULL) { this->data = NULL; return; } this->data = new T * [Rows]; for (int i = 0; i < Rows;i++) { this->data[i] = new T[Cols]; if (other.data[i] != NULL) { for (int j = 0;j < Cols;j++) { if (other.data[i][j] != NULL) { // 严重错误:非指针类型不能和NULL比较 this->data[i][j] = other.data[i][j]; std::cout << data[i][j] << std::endl; } } } } }
other.data[i][j]是模板类型T(默认是int),不是指针类型,不能和NULL比较,这会导致未定义行为- 所有构造器中分配的
data和data[i]都是通过new创建的有效指针,不可能为NULL,所以所有NULL判断都多余
修复后的拷贝构造器:
Matrix(const Matrix& other) { this->data = new T*[Rows]; for (int i = 0; i < Rows; i++) { this->data[i] = new T[Cols]; for (int j = 0; j < Cols; j++) { this->data[i][j] = other.data[i][j]; } } }
必须补充的赋值运算符重载
当前代码没有重载赋值运算符,编译器会生成默认的浅拷贝赋值运算符。这会导致两个Matrix对象共享data指针,当其中一个对象析构时,会释放内存,另一个对象再访问data就会触发错误,或者析构时重复释放内存导致崩溃。
添加深拷贝的赋值运算符:
Matrix& operator=(const Matrix& other) { if (this == &other) { // 防止自赋值 return *this; } // 释放当前对象已有的内存 for (int i = 0; i < Rows; i++) { delete[] data[i]; } delete[] data; // 分配新内存并拷贝数据 data = new T*[Rows]; for (int i = 0; i < Rows; i++) { data[i] = new T[Cols]; for (int j = 0; j < Cols; j++) { data[i][j] = other.data[i][j]; } } return *this; }
最终修复后的运算符*
将返回类型改为值返回,即可解决悬空引用问题,同时支持链式操作:
template<int Rows, int Cols, class T = int> Matrix<Rows, Cols> operator*(int n, const Matrix<Rows, Cols>& mat) { Matrix<Rows, Cols> temp; for (int i = 0;i < Rows;i++) { for (int j = 0;j < Cols;j++) { temp.data[i][j] = mat.data[i][j] * n; } } return temp; }
内容的提问来源于stack exchange,提问作者Ella
相关产品推荐
相关产品推荐

