c++ - 你能用复制赋值运算符创建一个新实例吗?

标签 c++ null new-operator copy-assignment

我正在研究 C++ 中的复制赋值运算符,我想知道如果对象为 null,是否有办法创建一个新实例。

class Person {
public:
    Person(string name) { pName_ = new string(name); }
    ~Person() { delete pName_; }
    Person(const Person& rhs) {
        if (pName_ != NULL) delete pName_;
        pName_ = new string(*(rhs.pName()));
    }
    Person& operator=(const Person& rhs) {
        cout << "begin copy..." << endl;
        if (this == NULL) {
            Person* p = new Person(rhs);
            cout << "end copy null..." << endl;
            return *p; // Not working?
        }
        delete pName_;
        pName_ = new string(*(rhs.pName()));
        cout << "end copy..." << endl;
        return *this;
    };
    string* pName() const { return pName_; }
    void printName() { cout << *pName_ << endl; }
private:
    string* pName_;
};
int main() {
    Person *a = new Person("Alex");
    Person *b = new Person("Becky");
    Person *c = NULL;
    *b = *a; // copy works
    *c = *a; // copy doesn't
    if (a != NULL) a->printName(); // Alex
    if (a != NULL) delete a;
    if (b != NULL) b->printName(); // Alex
    if (b != NULL) delete b;
    if (c != NULL) c->printName(); // NULL
    if (c != NULL) delete c;
    return 0;
}

这是输出:

begin copy...
end copy...
begin copy...
end copy null...
Alex
Alex

我是否可以在我的代码中更改某些内容以使其工作,或者这是我什至不应该尝试尝试的内容?

最佳答案

您显示的代码有各种错误,需要重写。

您正在通过取消引用的 NULL 指针调用未正确实现的复制赋值运算符,这是未定义的行为。复制赋值运算符被定义为仅对有效对象调用,并且必须将值从一个对象复制到另一个对象,并返回对复制到的对象的引用。你没有那样做。

要回答您的问题,不,当 this 为 NULL 时,复制赋值运算符无法创建新对象。对于初学者,如果 this 为 NULL,那么您的代码中有一个需要修复的错误。但即使 this 为 NULL,运算符也无法更新调用者的指针(假设首先使用了指针)以指向新的对象实例。 this 只是一个编译器生成的参数,包含被调用对象的内存地址,它不是调用者用于调用运算符的原始指针。因此,如果运算符确实在堆上分配了一个新对象,则该对象将在运算符退出时泄漏,因为调用者将没有指向该对象的指针以稍后释放它。

您的代码的正确版本应该看起来更像这样:

class Person {
public:
    Person(const string &name) : pName_(name) {}

    Person& operator=(const Person& rhs) {
        // if you remove these output statements then
        // this entire operator can be removed...
        cout << "begin copy..." << endl;
        if (this != &rhs) {
            pName_ = rhs.pName();
            cout << "non self copied..." << endl;
        }
        cout << "end copy..." << endl;
        return *this;
    }

    string pName() const {
        return pName_;
    }

    void printName() const {
        cout << pName_ << endl;
    }

private:
    string pName_;
};

int main() {
    Person *a = new Person("Alex");
    Person *b = new Person("Becky");
    Person *c = NULL;

    *b = *a;
    //*c = *a; UNDEFINED BEHAVIOR! 

    if (a) {
        a->printName();
        delete a;
    }

    if (b) {
        b->printName();
        delete b;
    }

    if (c) {
        c->printName();
        delete c;
    }

    return 0;
}

关于c++ - 你能用复制赋值运算符创建一个新实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49357112/

相关文章:

java - 无法理解带有new运算符的java语句

c++ - 为什么在对象构造函数中抛出新表达式时不调用释放函数?

C++ 2D vector 声明和调试器的元素访问

c++ - 如何实现可变 tuple_map 操作?

c++ - 将句子分为单词的 vector

java - 运算符在 Java 中如何工作以及为什么此方法返回 null?

java - Java 是否允许可空类型?

postgresql - 为什么 Postgres 在涉及唯一约束的情况下不一致地处理 NULL?

c++ - 为什么在 C 中允许对 int * arr[] 进行以下赋值?

c# - 打开新窗体,关闭旧窗体 C#