尽管返回了引用,但无法链接重载的赋值运算符

Unable to chain overloaded assignment operator despite returning a reference

本文关键字:链接 重载 赋值运算符 返回 引用      更新时间:2023-10-16

edit:我现在已经解决了这个问题,我愚蠢地删除了重载运算符中的整个包,然后试图在其中插入值。我写了一个函数来清除包而不删除它,现在它工作得很好。感谢大家的帮助。原文如下,以防其他人发现自己犯了同样的错误:

我见过很多其他初学者在链接重载=运算符时遇到问题,他们的问题几乎总是忘记在重载运算符中返回引用。然而,我相信我正在这样做,但我仍然无法正确地链接我过载的+运算符。

例如,如果我创建两个MagicBags,mb1和mb2,那么我设置

mb1 = mb2;

这将正确编译和运行。当我创建第三个MagicBag,mb3,时

mb3 = mb2 = mb1;

不会编译,并且我在重载运算符中得到了一个空指针。

这是我的操作员:

MagicBag& operator=(const MagicBag& other) {
if (this == &other) {
return *this;
}
this->~MagicBag();//clear calling bag
node<T> * a;//construct a temp node pointer to use as an iterator to loop over original bag and copy its contents
int tempSize = other.size - 1;
while (tempSize >= 0) {
a = other.first;
for (int i = 0; i < tempSize; i++) {
a = a->next;//get my null pointer here
}
tempSize--;
insert(a->value);
}
return *this;
}

析构函数是

~MagicBag() {
if (first == NULL)
return;
if (first->next == NULL) {
delete(first);
first = NULL;
return;
}
node<T> * a = first->next;
while (a != NULL) {
delete(first);
first = a;
a = a->next;
}
delete(first);
first = NULL;
}

插入函数是标准的4行插入,我怀疑这是问题所在。我做错了什么?我相信我的析构函数不是问题所在,但我是一个初学者,所以它很可能是问题所在,我也相信我在重载运算符中正确地返回了一个引用。在这篇经常被引用的文章中,我似乎遵循了重载的标准约定,所以我很困惑为什么这一次可以正确工作,但当被链接时却不能。我在那篇文章的链接文章中也看到,没有必要检查这两个论点是否相同,但删除这一点并不能解决问题。我做错了什么?

首先,代码应该编译!如果它达到了实际运行的状态,并且您"得到了一个空指针",这是一种不同类型的错误,但编译已经完成。

代码本身充满了问题。以下是我发现的(最后一个导致了你注意到的问题):

  1. this上调用析构函数总是错误。在少数情况下,有必要显式调用对象的析构函数,但所有这些都涉及在专用内存中显式构造对象,这通常是由于使用了过载的operator new()。如果您真的需要在其他地方使用析构函数的功能,请将其移动到一个专用函数中,例如,一个名为clear()的函数,并从析构函数以及其他需要它的地方调用它
  2. 赋值操作符有一个性能问题:遍历列表之类的东西很慢。为每个元素遍历列表的[部分]非常缓慢。实际上,在右侧的节点上迭代一次insert()每个节点的值更容易。也就是说,任务的核心可能只是

    for (node<T>* current = other.first; current; current = current->next) {
    insert(current->value);
    }
    

    由于这是复制构造函数所需的相同代码,所以我实际上会使用copy&交换习语:

    MagicBag& MagicBag::operator= (MagicBag const& other) {
    MagicBag(other).swap(*this);
    return *this;
    }
    

    其中CCD_ 5只是交换所有成员的内容。

  3. 严格来说,这不是一个错误,但你的析构函数太复杂了(因此我不能确定它是否正确)。我不知道你们班的所有人,但看起来可能是这样的:

    ~MagicBag() {
    for (node<T>* current = first; current; ) {
    node<T>* tmp = current->next;
    delete current;
    current = tmp;
    }
    }
    
  4. 从代码的外观来看,您得到了一个空指针解引用,因为您的析构函数和赋值运算符都没有调整this->size:代码没有显示,但我猜您的insert()函数只是增加了this->size。因此,在调用对象的析构函数后,赋值中可能有一个非零的this->size,每个新对象增加一次。由于赋值中的循环在other.size对象上移动,如果实际节点数比other.size所暗示的要少,则它最终将取消引用空指针。当右侧被分配给时正是这种情况。假设您创建了一个clear()函数,这应该将this->size设置为零(以及在节点delete之后将this->first设置为空指针)。