赋值运算符重载问题

发布于 2024-09-07 02:36:30 字数 1966 浏览 8 评论 0原文

这个问题让我很困惑。第一段代码工作正常,没有崩溃,它将 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

べ繥欢鉨o。 2024-09-14 02:36:30

删除当前的 val 并将其替换为 std::string。删除您的字段并将其替换为std::vector。这应该可以让您消除两个重载的赋值运算符;编译器将提供有效的。我猜你会消除内存管理问题以及代码。

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

Get rid of your current val and replace it with an std::string. Get rid of your fields and replace it with an std::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).

溺深海 2024-09-14 02:36:30
        for (int i = 0; i < scr.numOfFields; i++)
            fields[i] = scr.fields[i];

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

        for (int i = 0; i < scr.numOfFields; i++)
            fields[i] = scr.fields[i];

That's not okay, you are copying a pointer instead of the pointed-to value. A deep copy is required.

眼眸 2024-09-14 02:36:30

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

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.

霓裳挽歌倾城醉 2024-09-14 02:36:30

该行

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&),因此可能还需要将赋值运算符重载的修复应用于复制构造函数定义。

另外,Screenfields 成员是如何定义的?如果是这样:

LField* fields[50];

那么在构造函数中,您必须将数组中的所有 LField* 对象初始化为 NULL 因为它们具有未定义的初始值:

std::fill_n(fields, 50, static_cast<LField*>(NULL));

如果没有此初始化,测试即使 fields[i] 没有指向分配,if (fields[i]) 也可能对某些 i 成功,从而导致您的程序尝试删除未由new返回的指针。

The line

Screen s2 = s1;

actually invokes the Screen copy constructor, not the assignment operator overload.

For example:

#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;
}

prints:

in Screen::Screen(const Screen&)

I'm guessing that your Screen copy constructor is defined similar to Screen::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 of Screen defined? If it is like:

LField* fields[50];

then inside the constructors, you have to initialize all LField* objects in the array to NULL as they have undefined initial values:

std::fill_n(fields, 50, static_cast<LField*>(NULL));

Without this initialization, the test if (fields[i]) could succeed for some i even though fields[i] does not point to an allocation, causing your program to attempt to delete pointer(s) that were not returned by new.

剩余の解释 2024-09-14 02:36:30

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

I've manged to fix it. It was a problem with memory allocation after all :)

黯然#的苍凉 2024-09-14 02:36:30

对于复杂的对象,最好使用复制和交换 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.
}

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.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文