指针上的操作符=可能导致mac上的分段错误

operator= on pointers possibly causing a segmentation fault on mac

本文关键字:mac 错误 分段 操作符 指针      更新时间:2023-10-16

我想写一个类集与链表存储整数。在我的Mac终端上编译并运行后,输出如下:

[]
[10]
[10, 20]
Segmentation fault: 11

但是我期望看到以下输出:

[]
[10]
[10, 20]
[10, 20]
[10, 20, 30]

我想知道这是一个问题与我的操作符=函数,或者它是我不能使用操作符=函数与指针?如果是这样,我应该如何纠正这个问题,使程序如我所期望的那样输出?我将非常感谢你的帮助。提前感谢!

#include <iostream>
using namespace std;
class Node {
  public:
    int value;
    Node* next;
    Node(int n, Node* ptr = NULL) : value(n), next(ptr) {}
};
class Set {
  Node* head;
  friend ostream& operator<<(ostream&, const Set&);
  public:
    Set() : head(NULL) {}
    Set(const Set& another){ *this = another; }
    ~Set();
    Set& operator+=(const int&);
    Set& operator=(const Set&);
};
int main() {
    int num1 = 10;
    int num2 = 20;
    int num3 = 30;
    Set set1;
    cout << set1;
    Set* set2;
    set1 += num1;
    cout << set1;
    set1 += num2;
    cout << set1;
    set2 = new Set(set1);
    cout << *set2;
    *set2 += num3;
    cout << *set2;
    delete set2;
    return 0;
}
Set::~Set() {
    Node* current = head;
    while (current != NULL) {
        Node* temp = current;
        current = current->next;
        delete temp;
    }
}
Set& Set::operator+=(const int& aNum) {
    if (head == NULL) {
        head = new Node(aNum);
        return *this;
    }
    Node* previous = head;
    Node* current = head->next;
    while (current != NULL) {
        previous = current;
        current = current->next;
    }
    previous->next = new Node(aNum);
    return *this;
}
Set& Set::operator=(const Set& another) {
    if (this != &another) {
        Node* current = head;
        while (current != NULL) {
            Node* temp = current;
            current = current->next;
            delete temp;
        }
        Node* anotherCurrent = another.head;
        while (anotherCurrent != NULL) {
            *this += anotherCurrent->value;
            anotherCurrent = anotherCurrent->next;
        }
    }
    return *this;
}
ostream& operator<<(ostream& os, const Set& s) {
    os << "[";
    for (Node* p = s.head; p != NULL; p = p->next) {
        os << p->value;
        if (p->next != NULL)
            os << ", ";
    }
    os << "]" << endl;
    return os;
}

在复制之前删除之前的列表时,您必须将head设置为NULL,否则+=操作符将使用head,并且它当前未分配,但不是NULL

Set& Set::operator=(const Set& another) {
    if (this != &another) {
        Node* current = head;
        while (current != NULL) {
            Node* temp = current;
            current = current->next;
            delete temp;
        }
        head = NULL;   // <============== code to add
        Node* anotherCurrent = another.head;
        while (anotherCurrent != NULL) {
            *this += anotherCurrent->value;
            anotherCurrent = anotherCurrent->next;
        }
    }
    return *this;

顺便说一句,这是一个非常有趣的设计模式,必读:复制-交换习惯用法