简体   繁体   English

C ++复制/移动构造函数和赋值运算符

[英]C++ copy/move constructor and the assignment operator

I want to know about C++ copy/move constructor and assignment operator, let's first give code example: 我想了解C ++复制/移动构造函数和赋值运算符,让我们首先给出代码示例:

Header: 标头:

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;
};

Source: 资源:

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;
}

Now the question is: Does it really need in the copy and move constructors that we check for equality if this==&other ? 现在的问题是:如果this==&other是否真的需要我们检查是否相等的copymove构造函数? Because it is a constructor and it is impossible to be equal with other. 因为它是一个构造函数,所以不可能与其他函数相等。 And also Does it need that in the copy and move constructors we delete (free) the memory? 而且是否需要在copymove构造函数中delete (释放)内存? Because the memory has not been allocated yet, then why it needs to be deleted? 因为尚未分配内存,那么为什么需要删除它? I say this because I saw in many C++ tutorials that they deleted the memory and check for equality. 我之所以这样说,是因为我在许多C ++教程中看到他们删除了内存并检查是否相等。

So if I am right, then the copy and move constructor can be written like this: 所以如果我是对的,那么copymove构造函数可以这样写:

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;
}

And also how about checking for equality in move assignment? 还有,如何检查move分配中的相等性?

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

Thanks! 谢谢!

I want to know about C++ copy/move constructor and equal operator... 我想了解C ++复制/移动构造函数和相等运算符...

I think you meant the assignment operator operator= . 我认为您的意思是赋值运算operator= The equal operator would be operator== . 等于运算符将是operator==

Does it really need in the copy and move constructors that we check for equality if this==&other? 如果this ==&other,它真的需要在复制和移动构造函数中检查是否相等吗?

No, you don't need this as you already stated. 不,您不需要像已经说明的那样。

Does it need that in the copy and move constructors we delete (free) the memory? 是否需要在复制和移动构造函数中删除(释放)内存?

You'll need it in your move- and copy-assignment, because you have to release the old memory to copy (or just set the pointer to) the memory of the other Person . 您需要在移动和复制分配中使用它,因为必须释放旧的内存才能复制(或只是将指针设置到)另一个Person的内存。 Your constructor won't need a delete. 您的构造函数不需要删除。

So if I am right, then the copy and move constructor can be written like this 所以如果我是对的,那么复制和移动构造函数可以这样写

Yes, these are correct. 是的,这些是正确的。 Are you sure you really want to have fixed 100 bytes for every person? 您确定真的要为每个人固定100个字节吗?

And also how about checking for equality in move assignment? 还有,如何检查移动分配中的相等性?

I would not check for equality in move assignment, because move is a very inexpensive operation and it is very unlikely that you are going to assign the same object. 我不会在移动分配中检查是否相等,因为移动是一项非常便宜的操作,并且您不太可能分配相同的对象。

No, self-initialization check is not needed in constructor. 不,构造函数中不需要自初始化检查。 Mainly because it means you are trying to initialize object with uninitialized object, which is a bad idea. 主要是因为这意味着您试图使用未初始化的对象来初始化对象,这是一个坏主意。 Standard library just treats such use as undefined behavior. 标准库只是将此类使用视为未定义的行为。

Making sure that self-assignment works is something you should do, as it can happen in proper programs. 确保自赋值工作是您应该做的事情,因为它可以在适当的程序中发生。 But explicit check is something you should avoid: it forces everyone pay cost for that check, even if it is for something rarely happening. 但是您应该避免显式检查:它迫使每个人都为此检查支付费用,即使是很少发生的事情。 It is better to write your assignment operators to work properly even in case of self-assignment: 最好将您的分配运算符编写为即使在自我分配的情况下也可以正常工作:

Person &Person::operator=(Person &&other) noexcept
{
    using std::swap;
    swap(name, other.name);
    swap(age, other.age);
    return *this;
}

It works well in case of self-move assignment — swaps some data with itself. 在自动移动分配的情况下,它可以很好地工作—与自身交换一些数据。 If inlined, it will be likely completely optimised away entirely. 如果内联,则可能会完全优化掉。 In general, destruction of original name is deferred until other destruction, but no extra work is done, and there is no perfomance hit. 通常,原名的销毁会推迟到other销毁为止,但是不会做额外的工作,也不会造成性能损失。 Copy assignment can be written as: 副本分配可以写为:

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;
}

Same operations, no perfomance hit in general case, works in case of self-assignment, easy to make strong exception guarantee, if smart pointers are used instead of raw pointers. 如果使用智能指针而不是原始指针,则相同的操作在一般情况下不会影响性能,在自分配的情况下起作用,易于做出强有力的异常保证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM