这个问题让我很困惑。第一段代码工作正常而没有崩溃,它将s1完全分配给s2。但是第二组代码导致程序崩溃。
任何人都知道为什么会发生这种情况或问题是什么?
代码1 :(有效)
s1.add(10, 30, 25, "Test Screen", false);
s1.add(13, 10, 5, "Name:XXX", false);
s1.add(13, 18, 30);
s1.remove(-1);
Screen s2 = s1;
代码2 :(转让时崩溃)
Screen s1;
if (1 != s1.add(10, 30, 25, "Test Screen", false))
message("first add() has a problem");
else if (2 != s1.add(13, 10, 5, "Name:XXX", false))
message("second add() has a problem");
else if (3 != s1.add(13, 18, 30))
message("third add() has a problem");
else if (3 != s1.remove(-1))
message("first remove() has a problem");
else {
Screen s2 = s1;
}
屏幕类的分配运算符:
Screen& operator=(const Screen &scr) {
if (this != &scr){
for (int i = 0; i < 50; i++) {
if (fields[i])
delete fields[i];
fields[i] = new LField();
}
for (int i = 0; i < scr.numOfFields; i++)
fields[i] = scr.fields[i];
numOfFields = scr.numOfFields;
currentField = scr.currentField;
}
return *this;
}
Field类的赋值运算符:
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
if (lfieldobj.val) {
if (val)
delete[] val;
val = new char[strlen(lfieldobj.val) + 1];
strcpy(val, lfieldobj.val);
}
else{
//val = new char[1];
val = "";
}
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
非常感谢任何输入:)
答案 0 :(得分:2)
删除当前的val
并将其替换为std::string
。摆脱fields
并将其替换为std::vector
。这应该可以消除重载赋值运算符的两个;编译器将提供有效的。我猜你会消除代码中的内存管理问题。
就目前而言,即使您“修复”了解您所知道的内存管理问题,您仍然会面临这样一个事实,即您的代码在异常情况下完全不安全(并使用new
因此它基本上无法避免例外情况。)
答案 1 :(得分:2)
for (int i = 0; i < scr.numOfFields; i++)
fields[i] = scr.fields[i];
那不行,你正在复制指针而不是指向的值。需要深层复印。
答案 2 :(得分:1)
会员“字段”声明是什么?
LField* fields[50]
?
如果是,那么谁将左侧对象字段成员初始化为NULL
?我会说没有人...赋值运算符就像C ++中的复制构造函数一样,并且你在无效指针上调用delete。
答案 3 :(得分:1)
该行
Screen s2 = s1;
实际上调用Screen
复制构造函数,而不是赋值运算符重载。
例如:
#include <iostream>
using namespace std;
class Screen
{
public:
Screen() { }
Screen(const Screen& s)
{
cout << "in `Screen::Screen(const Screen&)`" << endl;
}
Screen& operator=(const Screen& s)
{
cout << "in `Screen::operator=(const Screen&)`" << endl;
return *this;
}
};
int main()
{
Screen s1;
Screen s2 = s1;
}
打印:
Screen::Screen(const Screen&)
中的
我猜你的Screen
拷贝构造函数的定义与Screen::operator=(const Screen&)
类似,因此修复赋值运算符重载也可能需要应用于拷贝构造函数定义。
此外,fields
Screen
成员的定义如何?如果是这样的话:
LField* fields[50];
然后在构造函数中,您必须将数组中的所有LField*
对象初始化为NULL
,因为它们具有未定义的初始值:
std::fill_n(fields, 50, static_cast<LField*>(NULL));
如果没有此初始化,即使if (fields[i])
未指向分配,导致程序尝试i
指针,但某些fields[i]
的测试delete
可能会成功s)未由new
返回。
答案 4 :(得分:0)
我设法解决了这个问题。毕竟这是内存分配的一个问题:)
答案 5 :(得分:0)
对于复杂的对象,最好使用复制和交换idum 这为您提供了具有强异常保证(事务安全)的赋值运算符。但这也意味着你只需要在一个地方(构造函数)考虑复杂的对象创建。
Screen& Screen::operator=(Screen const& rhs)
{
Screen tmp(rhs);
this->swap(tmp);
return *this;
}
void Screen::swap(Screen const& rhs) throw ()
{
// Swap each of the members for this with rhs.
// Use the same pattern for Field.
}