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

时间:2014-12-07 09:42:10

标签: c++ pointers copy-constructor

我读了somewhere

  

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

     
      
  1. 一个析构函数
  2.   
  3. 复制构造函数,
  4.   
  5. operator =(assignment)
  6.   

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

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

我举一个具体的例子:一个人出生在某个日期;日期是一个对象,它包含一天的值或一周中的哪一天。 我不想复制"一个人,但即使我必须,他们也不应该指向同一个Date对象吗?

如果是真的,为什么?

3 个答案:

答案 0 :(得分:5)

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

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

然而,最明智的做法是避免这样的指针支持std::unique_ptrstd::vector等数据管理类。

答案 1 :(得分:2)

这个词与#34;应该"之间有很大的不同。和#34;必须"。当我阅读你提出的文本时,这意味着我应该强烈考虑做这三件事,而不是绝对必要。逻辑,经验和可行性将胜过诸如适当时的指导原则。

话虽如此,如果它有意义,那么在你的班级中拥有这三件事总是好的。

答案 2 :(得分:0)

在你的日期示例中,那不应该是指针。如果是指针,则 你得到一个临时或副本,析构函数是做什么的?致电
日期对象上的delete?如果您拨打delete两次(现在有2个 对象指针,它的未定义行为。

关于 NOT 要执行的操作的示例:

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,那就会出错 很容易得到一份副本,暂时无处不在。

一种可能性是指针生命周期由其他人管理,
在这种情况下,指针可以看作更多的句柄,然后它就可以了 定义copy-constructor,asignment-operator和析构函数。

除非生命由其他人管理,否则你应该 根本不使用指针,要么直接使用值,要么使用智能指针。

不太好的例子:

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 ++中使用价值语义,它就是为此做的 看看Rule of Zero