c++ - 为什么我的代码结果显示分段错误(核心转储)?
问题描述
我已经创建了具有构造函数和运算符 + 重载以添加两个矩阵的类 mat(矩阵),但是当我编译并运行我的代码时,一切正常,直到我初始化我的 m1,m2 ..然后结果是“分段错误(核心转储)”。我不明白为什么它显示它?我没有在这里发布 ostream& 运算符 << 函数来缩短代码长度。
class mat{
int r,c;
float **p;
public:
mat(){}
mat(int,int);
mat(int,int,float);
void initialize();
mat operator+(mat); //defined
friend ostream& operator<<(ostream&,mat&);
};
void mat :: initialize(void){
int i,j;
cout<<"\nEnter the elements : ";
for(i=0;i<r;++i){
for(j=0;j<c;++j){
cin>>p[i][j];
}
}
return;
}
mat mat :: operator+(mat x){
mat tmp;
int i,j;
for(i=0;i<r;++i){
for(j=0;j<c;++j){
tmp.p[i][j]=(p[i][j])+(x.p[i][j]);
}
}
return tmp;
}
mat :: mat (int a, int b){
r=a;
c=b;
p=new float*[r];
for(int i=0; i<r; ++i){
p[i]=new float[c];
}
}
mat :: mat (int a, int b, float t){
r=a;
c=b;
p=new float*[r];
for(int i=0; i<r; ++i){
p[i]=new float[c];
}
for(int i=0;i<r;++i){
for(int j=0;j<c;++j){
p[i][j]=t;
}
}
}
int main(){
mat m1(3,3),m2(3,3),m3(3,3,0);
cout<<"\nInitialize M1";
m1.initialize();
cout<<"\nInitialize M2";
m2.initialize();
m3=m1+m2;
cout<<m3;
return(0);
}
我是编码新手。请用简单的语言帮助我。
解决方案
mat tmp;
中的未operator+
初始化。它使用默认的无参数构造函数,它什么都不做,特别是,不将p
指针设置为任何东西,这会在您尝试分配其内容时导致分段错误。一个好的 operator+ 应该检查两个矩阵是否具有相同的维度,并使用双参数构造函数创建结果矩阵。
这应该可以回答这个问题,但我也会详细说明 PaulMcKenzie 的评论,因为它很重要。
像这样的类在分配、移动或销毁时没有定义的特殊行为,这在处理原始指针时是不可接受的。例如,当您将此类的一个对象分配给另一个对象时,字段被简单地复制,这意味着两个对象共享同一个p
指针,这可能不是您想要的。您的对象在销毁时也不会清理其内存,这意味着您的程序中有多个内存泄漏。
为了拥有一个使用原始指针的功能类,您需要
mat(const& mat other);
- 复制构造函数
mat& mat::operator=(const& mat other);
- 复制赋值运算符
mat(mat&& other) noexcept;
- 移动构造函数(C++11 及以上)
mat& mat::operator=(mat&& other) noexcept;
- 移动赋值运算符(C++11 及以上)
~mat();
- 析构函数
如果您不提供析构函数,则每次销毁此类的对象时都会发生内存泄漏。如果你提供析构函数但复制/移动保持默认,它会崩溃,因为在你复制或移动一个对象后,两个对象将持有相同的p
指针,并且在两个对象被销毁后,指针将被释放两次导致崩溃。
正如 PaulMcKenzie 建议的那样,一个简单的解决方法是使用std::vector
,它为您完成了所有的内存管理。
如果您想自己编写它们,请查找“0 规则”/“3 规则”/“5 规则”。
在半相关的注释中,mat mat :: operator+(mat x)
被声明为错误,因为它创建了参数的不必要副本并且不是 const。声明它的正确方法是mat mat :: operator+(const mat& x) const
,它将参数作为 const 引用传递,并且本身也是 const ,这意味着它可以用于 const 变量。
推荐阅读
- angular - 以角度从 API 返回单个字符串值
- asp.net - 在 LocalHost IIS 上部署站点后无法访问某些文件夹的页面
- java - 获取给定父级的所有后代
- python-3.x - 将 google ml 引擎预测用于需要额外模块的 sci-kit 学习模型
- reactjs - 反应组件中的 onDeviceReady 事件监听器
- java - Spring Boot 全局控制器建议未在 Spring 上下文中加载
- node.js - 我们如何使用 schema.path 设置 required 等于 false?
- javascript - 一次单击时如何隐藏按钮将显示当前时间和日期
- laravel - 上传到服务器后的符号链接问题
- kubernetes - 在 kubernetes 中使用 pvc 时如何避免覆盖容器目录?