1

这个问题让我很困惑。第一段代码可以正常工作而不会崩溃,它将 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;
    }

任何投入将不胜感激 :)

4

6 回答 6

2

摆脱您的当前val并用std::string. 摆脱你的fields并用std::vector. 这应该让您消除两个重载的赋值运算符;编译器将提供那些可以工作的。我猜你会随着代码消除内存管理问题。

就目前而言,即使您“修复”了您所知道的内存管理问题,您也将面临这样一个事实,即您的代码在面对异常时完全不安全(并且new基本上使用它也不能避免例外)。

于 2010-06-21T14:29:59.593 回答
2
        for (int i = 0; i < scr.numOfFields; i++)
            fields[i] = scr.fields[i];

那不行,您正在复制指针而不是指向的值。需要深拷贝。

于 2010-06-21T14:31:08.340 回答
1

什么是成员“字段”声明?

LField* fields[50]?

如果是这样,谁将左侧对象字段成员初始化为NULL?我想说没有人...赋值运算符就像 C++ 中的复制构造函数,并且您正在对无效指针调用 delete。

于 2010-06-21T14:17:29.043 回答
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])也可能成功,导致您的程序尝试指向未返回的指针。ifields[i]deletenew

于 2010-06-21T14:33:16.747 回答
0

我已经设法修复它。毕竟这是内存分配的问题:)

于 2010-06-21T14:27:49.287 回答
0

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).

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.
}
于 2010-06-21T15:02:48.703 回答