复制构造函数和动态内存

Copy constructor and dynamic memory

我是编程初学者,正在学习复制构造函数。从不同的来源我可以看到,如果我想 "deep copy" 一个 class 对象,那么复制构造函数很有用,这样新对象的指针成员将指向新的内存位置。

我的问题是,如果我使用空复制构造函数(如 class空猫)?

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

无论是否使用空复制构造函数,您都不会获得相同的行为。 EmptyCat(EmptyCat& obj) { } 什么都不做。

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

动态分配一个新的 int 并为其分配一个来自 obj.

的值

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

在 C++ 中,new 现在已被有效弃用。我们有唯一的指针,它们是 "owning pointers" 和 "shared pointers"。但是,指针相对较少。 类的数组成员是std::vectors,字符串成员是std::strings。并且副本是自动深的,(如果你想要浅副本,你可以使用引用)。

指针在相对不寻常的情况下被阻止,例如树和图形。

My question is, what is the advantage of defining the copy constructor as I do in class CopyCat in my example, if I get the same result with an empty copy constructor (as in class EmptyCat)?

你不会得到相同的结果。 CopyCat 分配新内存 并且 从旧 class 复制值。 EmptyCat 只是分配新内存,但不复制值。

My second question is, why do class Cat and class EmptyCat work differently? The only difference between them is that I define an empty copy constructor in EmptyCat. But as I run the program I can see that in EmptyCat after the copying the pointer member points to a new location while in class Cat it works as a shallow copy.

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

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

int * itsAge = new int;

这就是分配新 int 并为您提供不同指针值的原因。