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%的时间内关心发生的事情的性能呢?与快速的自我分配相比,自我分配与所有其他分配一样快会更好,但其他分配都稍微慢一点。