C ++:类对象在重新分配中引用而不是复制

时间:2019-02-13 16:39:58

标签: c++

我有以下代码,其中创建了一个等待线对象,以节点的形式跟踪人员。 enterLine()函数将一个人添加到行中,并将他们之前的节点指向自己的节点。 exitLine()删除该行中的第一个人。

#include <iostream>
#include <string>
using namespace std;
struct node {
    string val;
    node *next;  // this will be the pointer to the person behind this person
};
class waitline {
public:
    waitline() {};
    void enterLine(string x);
    string exitLine();
    int size() { return len; };
    bool isEmpty() {
        if (len == 0) return true; else return false;
    };
    void printLine();
private:
    node * front = NULL, *rear = NULL;
    int len = 0;
};
void waitline::enterLine(string x) {
    if (len == 0) {
        front = new node;
        rear = front;
        front->val = x;
        front->next = NULL;
        len++;
    }
    else {
        rear->next = new node; // rear is the last person in line
        rear = rear->next;  //reset rear to the new node.
        rear->val = x;
        rear->next = NULL;
        len++;
    }

};
string waitline::exitLine() {
    string s;
    if (len == 0) {  // no one in line
        cout << "error-no one in line\n";
        return "";

    }
    else {
        s = front->val;
        front = front->next;
        len--;
        return s;
    }
};
void waitline::printLine() {
    node *temp;
    cout << "FRONT OF LINE\n";
    temp = front;
    while (temp != NULL) {
        cout << temp->val << endl;
        temp = temp->next;
    }
};
int main() {
    waitline w, w2;
    w.enterLine("Joe");
    w.enterLine("Mary");
    w.enterLine("Mikey");
    w2 = w;
    cout << "waiting line w2 is\n";
    w.printLine();
    cout << w.exitLine() << " was served\n";
    w2.enterLine("Susie");
    w.enterLine("Juan");
    w.enterLine("Nguyen");
    cout << w.exitLine() << " was served\n";
    w.printLine();
    cout << w.size() << endl;
    w2.printLine();
    return 0;
}

我希望w2只保留前3个值(Joe,Mary和Mikey)以及Susie,后者已显式添加到w2。但是,在打印w2时,它将提供我期望从printLine(w)获得的输出。

2 个答案:

答案 0 :(得分:3)

w2 = w进行浅表复制:复制指针,但不复制指向对象的指针。因此,也可以通过w来观察通过w对那些指向对象的更改。您需要进行深层复制,例如:通过正确实现operator=

rule of 3/5/0对资源处理对象需要实现的必需成员进行了很好的解释。

否则,正如其他评论者指出的那样:代码中存在几个内存管理问题。除非这是某种家庭作业,或者是故意学习指针的工作原理,否则使用标准容器(例如:std::vectorstd::dequeuestd::list)会更有效。

答案 1 :(得分:0)

我想以不同的方式陈述erenon的答案。问题是这行代码:

w2 = w;

这是将w的结构复制到w2中。也就是说,复制了w2.front,w2.rear和w2.length。他们指向的数据不是。

换句话说,w2.front指向与w.front完全相同的节点,而不是它的副本。因此,如果修改w2.front-> next,则同时修改w.front-> next,因为它与内存中的空间完全相同。

这几乎肯定不是您想要的。

如果要执行w2 = w,则需要实现一个复制运算符。您可以在google上找到如何编写示例。但是基本上,您要做的是遍历节点列表,创建一个重复列表,这样,等待线都不会真正指向相同的节点对象列表。

假设这就是您想要的-一个独特的NEW LINE,但是基于与原始行相同的字符串,因此对一个行的更改不会影响另一个。

不过,我不会那样做。我会在等待线上写另一个方法:

void copyFrom(waitline &orig) {
    for (node *ptr = orig.front; ptr != NULL; ptr = ptr->next) {
        enterLine(ptr->val);
    }
}

然后我将执行复制操作,而不是复制操作:

w2.copyFrom(w);

这与编写复制操作符几乎相同,但是由于您是新手,因此无需学习复制操作符语义,也无需了解指针。