复制赋值运算符说明

Mag*_*GAT 2 c++ class operator-overloading copy-assignment

我正在为我创建的一个类编写一个复制赋值运算符,我使用以前的帖子作为指导: 什么是三法则?

我对这个人解释的一个方面有点困惑。

这是他们的课:

class person
{
    char* name;
    int age;
};
Run Code Online (Sandbox Code Playgroud)

这是我用作参考的复制赋值运算符定义(至少提供了 2 个):

// 2. copy assignment operator
person& operator=(const person& that)
{
    char* local_name = new char[strlen(that.name) + 1];
    // If the above statement throws,
    // the object is still in the same state as before.
    // None of the following statements will throw an exception :)
    strcpy(local_name, that.name);
    delete[] name;
    name = local_name;
    age = that.age;
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

我发现令人困惑的是,为什么他们包括这条线delete[] name;

这是他们提供的另一个示例:

person& operator=(const person& that)
{
    if (this != &that)
    {
        delete[] name;
        // This is a dangerous point in the flow of execution!
        // We have temporarily invalidated the class invariants,
        // and the next statement might throw an exception,
        // leaving the object in an invalid state :(
        name = new char[strlen(that.name) + 1];
        strcpy(name, that.name);
        age = that.age;
    }
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

我立即避开了这个,因为我不明白为什么函数会检查if(this != &that)然后在一个似乎还没有生成的数组上运行 delete (delete[] name;)。调用赋值运算符时,是否在调用复制赋值运算符函数之前立即调用常规构造函数?因此意味着我们必须删除由类构造函数生成的数组,因为它只能充满垃圾数据?

为什么我不能只写: name = that.name

name = new char[that.name.size()];
for (int i = 0; i < that.name.size(); i++)`
{
  name[i] = that.name[i]
}
Run Code Online (Sandbox Code Playgroud)

这可能是非常基本的,我应该只实现帖子建议的内容,但我的实际用例涉及struct具有多个成员的s数组,所以我在理解我到底需要做什么时有点困难。

我意识到这里有 2.5 个问题。任何见解将不胜感激。

这是我第一次实现自定义复制构造函数和复制赋值运算符,我相信在我做过几次之后它看起来会很容易。

提前致谢。

Yks*_*nen 7

所有这些都是确保正确管理内存所必需的。

如果我理解正确,您需要回答何时operator=实际调用?
好吧,operator=总是在存在两个有效对象时调用。其中之一被分配给,第二个是数据源。在此操作之后,两个对象必须仍然有效

这意味着比在内部operator=this有为字符串分配内存的对象(在其中一个构造函数中分配)和that对象,还为另一个字符串分配了内存。

我发现令人困惑的是,为什么他们包括这条线delete[] name;

我们必须首先清理当前驻留在thisobject 中的内存,否则在为它分配新的 momry 后我们会丢失这个指针。

调用赋值运算符时,是否在调用复制赋值运算符函数之前立即调用常规构造函数?

不。对象已经存在,这operator=就是调用的原因(而不是复制构造函数)。

因此意味着我们必须删除由类构造函数生成的数组,因为它只能充满垃圾数据?

它充满了有效数据。您的对象已构建,其中包含一些数据,然后您将其他内容分配给该对象。


附录:何时调用复制构造函数,何时operator=调用?(有关更多详细信息,请参阅此问题):

class A{};

int main()
{
    A a1; //default constructor 
    A a2 = a1; //copy-constructor, not assignment operator! New object is needed

    A a3; 
    a3 = a1; //we have valid and existing object on the left side, assignment operator is used
}
Run Code Online (Sandbox Code Playgroud)