复制构造函数和运算符=是必须的

Are copy constructor and operator= a must?

本文关键字:必须的 运算符 构造函数 复制      更新时间:2023-10-16

我在某处读到:

具有指针数据成员的每个类都应包含以下成员函数:

  1. 析构函数
  2. 复制构造函数,
  3. 运算符 =(赋值(

这是真的吗?如果复制对象没有意义怎么办?

如果相关指针数据成员指向不需要复制或无法更改的内容,该怎么办?

我举一个具体的例子:一个人出生在某个日期;Date 是一个对象,它保存诸如一天有多长或一周中的哪一天等值。我不想"复制"一个人,但即使我必须这样做,他们不应该指向同一个 Date 对象吗?

如果这是真的,为什么?

指针数据成员可能意味着不同的东西。如果指针只是一个观察指针(指向在其他地方管理的对象(,那么编译器生成的复制构造函数和运算符(它们只是复制指针的值(绝对没有问题。这里的潜在问题是指针的寿命可能超过对象,使其成为悬指针。

如果它是指向堆上分配并由 this 管理的内存的指针,则必须确保正确完成复制。简单地不实现 copy(构造函数和运算符(不是一种选择,因为编译器会自动创建它们,而这些很可能不会做你想要的。从 2011 年开始(使用 C++11(,您当然可以=delete复制和/或实现移动(构造函数和运算符(。

但是,最明智的做法是避免使用此类指针,以支持数据管理类,例如std::unique_ptrstd::vector等。

"应该"这个词和"必须"这个词有很大的区别。 当我读到你提出的案文时,它的意思是我应该强烈考虑做这三件事,而不是说这是绝对必要的。 逻辑、经验和可行性将胜过诸如适当时和地点的指导方针。

话虽如此,如果有意义,在你的课堂上有这三件事总是好的。

在您的日期示例中,这不应该是一个指针。如果是指针,
你得到一个临时的,或者一个副本,析构函数是做什么的?叫
delete日期对象?如果您两次致电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;
};

更好的例子

class Persson
{
public:
    Persson( string name, string date )
        : m_name(name)
    {
        ParseDate( m_date, date );
    }
private:
    string m_name;
    Date m_date;
};

始终在C++中使用值语义,它就是为此而生的。
看看零法则