在复制构造函数中复制任何指针成员变量

Making copy of any pointer member varible in copy constructor

本文关键字:复制 成员 变量 指针 构造函数 任何      更新时间:2023-10-16

我有一个类B,它有一个成员是指向a类对象的指针。在类型A的对象上使用复制构造函数时,它被复制,但成员变量不被复制。有没有一种方法可以复制A对象并自动复制它的B成员?下面的代码显示了我试图解释的问题:

class A
{
public:
    A(char t_name)
    {
        name = t_name;
    }
    ~A()
    {
    }
    char name;
};
class B
{
public:
    A* attribute;
    B()
    {
        attribute = new A('1');
    }
    ~B()
    {}
};

int main()
{
    B* b_variable = new B;
    B* b_copy = new B(*b_variable);
    return 0;
}

在A类型对象上使用复制构造函数时,复制该对象,但不复制成员变量。

你的代码从未在类a中调用任何复制构造函数。

你的代码调用类B中的复制构造函数,它做的正是应该做的,即复制attribute的值,这是一个指针到类a对象。

换句话说,在执行代码之后,你有两个类B实例和一个类A实例。在两个B类实例中,attribute指向同一个A类实例。

这(很可能)不是你想要的。

正如许多人已经指出的那样(例如,参见@lostbard answer),您需要在类B中使用复制构造函数来执行深度复制。因为类B有一个指针成员,所以需要进行深度复制。

你也应该在类B的析构函数和main中做一些清理。

#include <iostream>
using namespace std;
class A
{
public:
    A(char t_name)
    {
        name = t_name;
    }
    ~A()
    {
    }
    char name;
};
class B
{
public:
    A* attribute;
    B()
    {
        attribute = new A('1');
    }
    /** Copy constructor */
    B(const B &copy)
    {
        // Make a new instance of class A
        attribute = new A(*copy.attribute);
    }
    /** Assignment operator */
    B& operator= (const B& other)
    {
        // Delete the existing class A instance
        delete attribute;
        // and create a new as a copy of other.attribute
        attribute = new A(*other.attribute);
    }
    ~B()
    {
        // Delete the class A instance
        delete attribute;
    }
};

int main()
{
    B* b_variable = new B;
    B* b_copy = new B(*b_variable);
    // Delete the two class B instances
    delete b_variable;
    delete b_copy;
    return 0;
}

类a中不需要复制构造函数,因为类a没有指针成员,所以默认生成的构造函数就可以。

编辑

正如@Slava指出的,当你创建复制构造函数时,你应该总是实现一个赋值操作符(三规则),所以我把它添加到上面的代码中。

有些人把"三规则"当作"五规则",所以它也包括"移动"。阅读更多:https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)

虽然有许多解决方案,但我敢打赌您迟早会实现通常的虚拟a.clone();。当您有A的派生类时,这种方法可以完美地工作(这或多或少是您将A保留为指向堆分配对象的指针而不是值成员的唯一合法原因:))。

注意,当您在层次结构中实现clone()时,c++支持协变指针返回类型。因此,如果base有一个返回Clonable*的虚函数,那么A的相同方法可以返回A*,而a的后代ADerived可以返回ADerived*。对于clone(),可以随意将can理解为should。

创建a和B的复制构造函数:

class A
{
public:
    A(char t_name)
    {   
    name = t_name;
    }
    A(const A& copy)
    {   
        name = copy.name;
    }
    ~A()
    {
    }
    char name;
};
class B
{
public:
    A* attribute;
    B()
    {
        attribute = new A('1');
    }
    B(const B &copy)
    {
      attribute = new A(*copy.attribute);
    }
    ~B()
    {}
};