复制构造函数和动态内存

时间:2017-02-08 00:06:41

标签: c++ copy-constructor deep-copy

我是编程的初学者,我正在学习复制构造函数。从不同的来源我可以看到,如果我想要深度复制"复制构造函数是有用的。一个类对象,所以新对象的指针成员将指向新的内存位置。

我的问题是,如果我在空副本构造函数中获得相同的结果(如在类EmptyCat中),那么在我的示例中类CopyCat中定义复制构造函数的优点是什么?

我的第二个问题是,为什么班级Cat和班级EmptyCat的工作方式不同?它们之间的唯一区别是我在EmptyCat中定义了一个空的复制构造函数。但是当我运行程序时,我可以看到在复制指针成员指向新位置之后在EmptyCat中,而在类Cat中它作为浅拷贝工作。

#include "iostream"

class Cat
{
  public:
    void GetMem() { std::cout << itsAge << "\n"; }
  private:
    int * itsAge = new int;
};

class EmptyCat
{
  public:
    EmptyCat() {}
    ~EmptyCat() {}
    EmptyCat(EmptyCat&obj) {}
    void GetMem() { std::cout << itsAge << "\n"; }
  private:
    int * itsAge = new int;
};

class CopyCat
{
  public:
    CopyCat() {}
    ~CopyCat() {}
    CopyCat(CopyCat&obj);
    int GetAge() { return *itsAge; }
    void GetMem() { std::cout << itsAge << "\n"; }
  private:
    int * itsAge = new int;
};

CopyCat::CopyCat(CopyCat & obj)
{
    itsAge = new int;
    *itsAge = obj.GetAge();
}

int main()
{
    Cat Garfield;
    Cat Kitty(Garfield);

    std::cout << "Memory addresses for the objects' <itsAge> member:" << std::endl;
    std::cout << "Garfield and Kitty (Class Cat):" << std::endl;
    Garfield.GetMem();
    Kitty.GetMem();

    EmptyCat Meow;
    EmptyCat Purr(Meow);

    std::cout << std::endl << "Meow and Purr (Class EmptyCat):" << std::endl;
    Meow.GetMem();
    Purr.GetMem();

    CopyCat Fluffy;
    CopyCat Felix(Fluffy);

    std::cout << std::endl << "Fluffy and Felix (Class CopyCat):" << std::endl;
    Fluffy.GetMem();
    Felix.GetMem();

    system("pause");
    return 0;
}

如果我运行程序,我会得到这个:

Memory addresses for the objects' <itsAge> member:
Garfield and Kitty (Class Cat):
00BBDA60
00BBDA60

Meow and Purr (Class EmptyCat):
00BB46A0
00BB8280

Fluffy and Felix (Class CopyCat):
00BB82B0
00BBE8A0
Press any key to continue . . .

3 个答案:

答案 0 :(得分:0)

使用和不使用空副本构造函数时,您没有获得相同的行为。 EmptyCat(EmptyCat& obj) { }绝对没有。

CopyCat(CopyCat& obj) {
  itsAge = new int;
  *itsAge = obj.GetAge();
}

动态分配新的int,并为其分配obj中的值。

答案 1 :(得分:0)

深度复制和浅层复制是一个C概念,只有结构和原始指针。指针可以被拥有,在这种情况下副本必须是深的,或者它可以被共享,在这种情况下副本是浅的(如果它被分配了malloc,你必须小心释放它)。 / p>

在C ++中,new现在已被有效弃用。我们有独特的指针,它们拥有指针&#34;和#34;共享指针&#34;。然而,指针是相对罕见的。类的数组成员是std :: vectors,字符串成员是std :: strings。副本会自动深入,(如果需要浅拷贝,可以使用参考)。

指针会因相对不寻常的情况而受阻,例如树木和图表。

答案 2 :(得分:0)

  

我的问题是,如果我在空副本构造函数中获得相同的结果(如在类EmptyCat中),那么在我的示例中类CopyCat中定义复制构造函数的优点是什么?

你没有得到相同的结果。 CopyCat分配新内存复制旧类的值。 EmptyCat只分配新内存,但不复制值。

  

我的第二个问题是,为什么班级Cat和班级EmptyCat的工作方式不同?它们之间的唯一区别是我在EmptyCat中定义了一个空的复制构造函数。但是当我运行程序时,我可以看到在复制指针成员指向新位置之后在EmptyCat中,而在类Cat中它作为浅拷贝工作。

Cat中,您尚未声明复制构造函数,因此编译器将在需要时生成一个复制构造函数。默认的复制构造函数从原始复制构件执行成员复制。在您的情况下,这将复制指针(以便它存储与原始地址相同的地址)。

EmptyCat中,您拥有用户定义的复制构造函数。但由于那个不处理指针成员,因此将使用其默认值。

int * itsAge = new int;

这是分配新int并获得不同指针值的原因。