C++;复制/移动构造函数和赋值运算符 我想了解C++复制/移动构造函数和赋值运算符,首先给出代码例子:

C++;复制/移动构造函数和赋值运算符 我想了解C++复制/移动构造函数和赋值运算符,首先给出代码例子:,c++,C++,标题: class Person { public: Person(); Person(const char * name, int age); Person(const Person &person); Person(Person&&) noexcept; virtual ~Person(); Person &operator=(const Person & other); Person &am

标题:

class Person
{
public:
    Person();
    Person(const char * name, int age);
    Person(const Person &person);
    Person(Person&&) noexcept;

    virtual ~Person();

    Person &operator=(const Person & other);
    Person &operator=(Person &&other) noexcept;

    char *getName() const;
    int getAge() const;

private:
    char *name;
    int age = 0;
};
Person::Person() : age(0)
{
    this->name = new char[100];
    memset(this->name, 0, sizeof(char)*100);
}

Person::Person(const char * name, int age) : Person()
{
    std::strcpy(this->name, name);
    this->age = age;
}

Person::Person(const Person &person)
{
    if(this == &person)
    {
        return;
    }
    //delete[](name);
    this->name = new char[100];
    memset(this->name, 0, sizeof(char)*100);
    std::strcpy(name, person.name);
    age = person.age;
}

Person::Person(Person &&other) noexcept
{
    if(this == &other)
    {
        return;
    }
    //delete[](name);
    name = other.name;
    age = other.age;
    other.name = nullptr;
    other.age = 0;
}

Person &Person::operator=(const Person &other)
{
    if(this == &other)
    {
        return *this;
    }
    delete[](name);
    name = new char[100];
    memset(name, 0, sizeof(char)*100);
    std::strcpy(name, other.name);
    age = other.age;
    return *this;
}

Person &Person::operator=(Person &&other) noexcept
{
    if(this == &other)
    {
        return *this;
    }
    delete[](name);
    name = other.name;
    age = other.age;
    other.name = nullptr;
    other.age = 0;
    return *this;
}

Person::~Person() {
    delete[](name);
    name = nullptr;
}
来源:

class Person
{
public:
    Person();
    Person(const char * name, int age);
    Person(const Person &person);
    Person(Person&&) noexcept;

    virtual ~Person();

    Person &operator=(const Person & other);
    Person &operator=(Person &&other) noexcept;

    char *getName() const;
    int getAge() const;

private:
    char *name;
    int age = 0;
};
Person::Person() : age(0)
{
    this->name = new char[100];
    memset(this->name, 0, sizeof(char)*100);
}

Person::Person(const char * name, int age) : Person()
{
    std::strcpy(this->name, name);
    this->age = age;
}

Person::Person(const Person &person)
{
    if(this == &person)
    {
        return;
    }
    //delete[](name);
    this->name = new char[100];
    memset(this->name, 0, sizeof(char)*100);
    std::strcpy(name, person.name);
    age = person.age;
}

Person::Person(Person &&other) noexcept
{
    if(this == &other)
    {
        return;
    }
    //delete[](name);
    name = other.name;
    age = other.age;
    other.name = nullptr;
    other.age = 0;
}

Person &Person::operator=(const Person &other)
{
    if(this == &other)
    {
        return *this;
    }
    delete[](name);
    name = new char[100];
    memset(name, 0, sizeof(char)*100);
    std::strcpy(name, other.name);
    age = other.age;
    return *this;
}

Person &Person::operator=(Person &&other) noexcept
{
    if(this == &other)
    {
        return *this;
    }
    delete[](name);
    name = other.name;
    age = other.age;
    other.name = nullptr;
    other.age = 0;
    return *this;
}

Person::~Person() {
    delete[](name);
    name = nullptr;
}
现在的问题是:它真的需要在
copy
move
构造函数中,如果
this==&other
检查相等性吗?因为它是一个构造函数,不可能与其他构造函数相等。它还需要在
复制
移动
构造函数中我们
删除
(释放)内存吗?因为内存尚未分配,那么为什么需要删除它?我这么说是因为我在许多C++教程中看到他们删除了内存并检查了相等性。p> 因此如果我是对的,那么
copy
move
构造函数可以这样编写:

Person::Person(const Person &person) : Person()
{
    std::strcpy(name, person.name);
    age = person.age;
}
Person::Person(Person &&other) noexcept
{
    name = other.name;
    age = other.age;
    other.name = nullptr;
    other.age = 0;
}
还有,在
move
赋值中检查相等性如何

Person &Person::operator=(Person &&other) noexcept
谢谢

我想知道C++复制/移动构造函数和相等运算符…< /P> 我想你指的是赋值运算符

运算符=
。相等运算符应为
运算符==

在复制和移动构造函数中,如果this==&other,是否真的需要检查相等性

不,你不需要这个,你已经说过了

是否需要在复制和移动构造函数中删除(释放)内存

在移动和复制任务中,您需要它,因为您必须释放旧内存来复制(或只是将指针设置为指向)另一个人的内存。您的构造函数不需要删除

如果我是对的,那么复制和移动构造函数可以这样写

是的,这些是正确的。您确定要为每个人固定100字节吗

还有,在移动赋值中检查相等性如何

Person &Person::operator=(Person &&other) noexcept

我不会在move赋值中检查相等性,因为move是一个非常便宜的操作,并且不太可能分配相同的对象。

不,构造函数中不需要自初始化检查。主要是因为这意味着您试图用未初始化的对象初始化对象,这是一个坏主意。标准库只是将这种使用视为未定义的行为

确保自我分配有效是你应该做的事情,因为它可以在适当的程序中发生。但明确的检查是你们应该避免的:它迫使每个人为检查付出代价,即使这是为了一些很少发生的事情。最好编写赋值运算符,使其即使在自赋值的情况下也能正常工作:

Person &Person::operator=(Person &&other) noexcept
{
    using std::swap;
    swap(name, other.name);
    swap(age, other.age);
    return *this;
}
在自动移动分配的情况下,它工作得很好-与自身交换一些数据。如果是内联的,它可能会被完全优化。通常,原始名称的销毁会推迟到
other
销毁,但不会进行额外的工作,也不会出现性能命中。副本分配可以写为:

Person &Person::operator=(const Person &other)
{
    using std::swap;
    auto new_name = new char[100];
    memset(new_name, 0, sizeof(char)*100);
    std::strcpy(new_name, other.name);
    swap(name, new_name);
    age = other.age;
    delete[](new_name);
    return *this;
}

相同的操作,在一般情况下没有性能影响,在自赋值的情况下工作,如果使用智能指针而不是原始指针,则很容易产生强烈的异常保证。

这两种操作通常仅在赋值运算符中完成。我不能说我记得曾经遇到过一个学习资源,它在构造函数中也可以。不太可能有人会尝试用它自己初始化变量。不过,我不会费心去查。如果使用我的代码的人想要自焚,这是他们的特权。@StoryTeller你能告诉我为什么你会说“尽管如此,我不会费心检查”吗?这里的
this
即使在自身初始化的情况下也永远不会等于
&other
,因为
this
刚刚构造,但是
&other
已经构造。因此,如果像这样做,`if(this==&other')是没有意义的。
this
可以等于
&other
,这是允许的,就像我链接到的代码一样(注意这是一个警告…)。不过,我也不想麻烦了,因为这样编写的代码可能会以多种方式被破坏,阻止别人破坏自己不是你的工作。很好,很清楚,谢谢!顺便说一句,100字节只是用于测试目的。是的,你说得对,是作业接线员。谢谢你的回复!在赋值运算符中,如果我们使用
swap()
,那么在自赋值的情况下,如果数据太大,那么如果我们不检查相等性,性能损失是多少?虽然您已经提到过,但我想知道,在自分配的情况下,
swap()
是否忽略复制过程?@BahramdunAdil swap通常被定义为一系列成员式移动,并且移动速度很快(您希望swap速度快,而noexept)。在您的例子中,它是指针和整数交换。这两种操作都非常快。如果编译器检测到该自赋值,它会将其优化为no-op。否则会发生交换(以及在拷贝赋值的情况下的内存分配),但为什么您会在0.001%的时间内关心发生的事情的性能呢?与快速的自我分配相比,自我分配与所有其他分配一样快会更好,但其他分配都稍微慢一点。