赋值运算符重载问题
这个问题让我很困惑。第一段代码工作正常,没有崩溃,它将 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;
}
字段类的赋值运算符:
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;
}
任何输入将不胜感激:)
This issue has me confused. The first piece of code works fine without crashing, it assigns s1 to s2 perfectly fine. But the second group of code causes the program to crash.
Anyone have any idea on why this is happening or what the problem could be?
Code 1:(works)
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;
Code 2:(crashes on assignment)
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;
}
Assignment operator for screen class:
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;
}
Assignment operator for Field class:
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;
}
Any input would be greatly appreciated :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
删除当前的
val
并将其替换为std::string
。删除您的字段
并将其替换为std::vector
。这应该可以让您消除两个重载的赋值运算符;编译器将提供有效的。我猜你会消除内存管理问题以及代码。就目前而言,即使您“修复”了您所知道的内存管理问题,您也将面临这样一个事实:您的代码在面对异常时是完全不安全的(并且使用
new
所以它基本上也无法避免异常)。Get rid of your current
val
and replace it with anstd::string
. Get rid of yourfields
and replace it with anstd::vector
. That should let you eliminate both of your overloaded assignment operators; the compiler will provide ones that work. I'd guess you'll eliminate the memory management problems along with the code.As it stands right now, even if you "fix" the memory management problem(s) you know about, you're going to be left with the fact that your code is completely unsafe in the face of exceptions (and uses
new
so it basically can't avoid exceptions either).这是不行的,您正在复制指针而不是指向的值。需要深拷贝。
That's not okay, you are copying a pointer instead of the pointed-to value. A deep copy is required.
什么是成员“字段”声明?
LField* 字段[50]
?如果是这样,谁将左侧对象字段成员初始化为
NULL
?我想说没有人...赋值运算符就像 C++ 中的复制构造函数,并且您在无效指针上调用删除。What's the member "field" declaration?
LField* fields[50]
?If so, who's initializing the left hand side object fields member to
NULL
? I'd say that nobody... assignment operator is like copy constructor in C++, and you're invoking delete on a invalid pointer.该行
实际上调用了 Screen 复制构造函数,而不是赋值运算符重载。
例如:
打印:
我猜测您的
Screen
复制构造函数的定义类似于Screen::operator=(const Screen&)
,因此可能还需要将赋值运算符重载的修复应用于复制构造函数定义。另外,
Screen
的fields
成员是如何定义的?如果是这样:那么在构造函数中,您必须将数组中的所有
LField*
对象初始化为NULL
因为它们具有未定义的初始值:如果没有此初始化,测试即使
fields[i]
没有指向分配,if (fields[i])
也可能对某些i
成功,从而导致您的程序尝试删除
未由new
返回的指针。The line
actually invokes the
Screen
copy constructor, not the assignment operator overload.For example:
prints:
I'm guessing that your
Screen
copy constructor is defined similar toScreen::operator=(const Screen&)
, so a fix for the assignment operator overload may need to be applied to the copy constructor definition as well.Also, how is the
fields
member ofScreen
defined? If it is like:then inside the constructors, you have to initialize all
LField*
objects in the array toNULL
as they have undefined initial values:Without this initialization, the test
if (fields[i])
could succeed for somei
even thoughfields[i]
does not point to an allocation, causing your program to attempt todelete
pointer(s) that were not returned bynew
.我已经设法修复它。毕竟这是内存分配的问题:)
I've manged to fix it. It was a problem with memory allocation after all :)
对于复杂的对象,最好使用复制和交换 idum。
这为您提供了一个具有强大异常保证(事务安全)的赋值运算符。但这也意味着您只需在一处(构造函数)考虑对象的复杂创建。
For complicated objects it is better to use the copy and swap idum.
This gives you an assignment operator with the strong exception gurantee (transactionaly safe). But it also means that you only have to consider the complicated creation of the object in one place (the constructors).