C++ 复制构造函数和运算符是否必须?
我读到: 具有指针数据成员的每个类都应包括以下成员函数:C++ 复制构造函数和运算符是否必须?,c++,pointers,copy-constructor,C++,Pointers,Copy Constructor,我读到: 具有指针数据成员的每个类都应包括以下成员函数: 破坏者 复制构造函数 运算符=(赋值) 这是真的吗?如果复制对象没有意义怎么办 如果问题中的指针数据成员指向不需要复制或无法更改的内容,该怎么办 我将给出一个具体的例子:一个人出生在某个日期;Date是一个对象,它保存诸如一天的长度或一周中的哪一天之类的值。 我不想“复制”一个人,但即使我不得不这样做,他们不应该指向同一个日期对象吗 如果这是真的,为什么 单词“应该”和“必须”之间有很大的区别。当我阅读你提出的文本时,这意味着我应该强烈地
如果这是真的,为什么 单词“应该”和“必须”之间有很大的区别。当我阅读你提出的文本时,这意味着我应该强烈地考虑做这三件事,而不是绝对必要。逻辑、经验和可行性将在适当的时候和地方压倒指导方针
也就是说,如果有意义的话,在你的类中有这三样东西总是好的。指针数据成员可以表示不同的东西。如果指针只是一个观察指针(指向其他地方管理的对象),那么编译器生成的复制构造函数和运算符(只复制指针的值)绝对没有问题。这里的一个潜在问题是,指针可能比对象寿命长,使其成为悬空指针 如果它是一个指向堆上分配的并由
this
管理的内存的指针,那么您必须确保正确地进行复制。简单地不实现copy(构造函数和操作符)不是一个选项,因为编译器将自动创建它们,而这些很可能不会实现您想要的功能。从2011年开始(使用C++11),您当然可以删除拷贝和/或实现移动(构造函数和操作符)
但是,最明智的做法是避免使用此类指针,而使用诸如
std::unique_ptr
或std::vector
等数据管理类。在日期示例中,这实际上不应该是指针。如果是指针,如果你得到一份临时文件,或者一份副本,析构函数的作用是什么?呼叫
删除日期对象上的
?如果您两次调用delete
(您现在有2个对象),它的未定义行为。
关于不做什么的示例:
class Persson
{
public:
Persson( string name, string date )
: m_name(name)
{
m_date = new Date;
ParseDate( *m_date, date );
}
~Persson()
{
delete m_date;
}
private:
string m_name;
Date* m_date;
};
如果你曾经复制过一个Persson
,这会出错。复印件很容易,临时的到处都是 一种可能是指针生命周期由其他人管理,
在这种情况下,指针可以更多地看作是一个句柄,那么它就没有问题了
定义复制构造函数、赋值运算符和析构函数 除非对象的生命周期由其他人管理,否则您应该
根本不使用指针,直接使用值或智能指针。
不那么坏的例子:
class Persson
{
public:
Persson( string name, string date )
: m_name(name)
{
m_date = make_shared<Date>();
ParseDate( *m_date.get(), date );
}
private:
string m_name;
shared_ptr<Date> m_date;
};
总是使用C++的值语义,它是为.bR>所做的。
看看你的例子不清楚。日期对象在哪里分配和删除?如果在构造函数/析构函数中,则会出现严重错误,因为复制的Person对象的析构函数可以删除原始Person对象的Date成员。如果分配/事务发生在类之外,那么就可以了,但它不是典型的C++风格。在对象存在之前,DATE被分配(我有一个数据指针带有日期指针),一个人构造函数包含一个字符串,并且它找到了合适的日期指针。同一个生日的人将共享同一个日期。日期独立。它可以由不同的人使用,在程序开始时分配,在程序结束时删除。这是一个生命周期由其他人管理的对象的示例。您可以使用指针,默认的复制构造函数等将做正确的事情。但是为什么要这样设计
Date
?我看不出std::unique\u ptr或std::vector在这里有什么帮助。也许你的意思是std::shared_ptr需要你努力实现的目标。如果指针指向this
拥有的内存,则std::unique\u ptr
或std::vector
是最好的<代码>std::shared_ptr通常不是类的好成员类型。
class Persson
{
public:
Persson( string name, string date )
: m_name(name)
{
ParseDate( m_date, date );
}
private:
string m_name;
Date m_date;
};