C++ 拷贝构造函数



C++ 中的拷贝构造函数

拷贝构造函数 是一种构造函数,用于创建已存在的类对象的副本,它通常采用 X (X&) 的形式,其中 X 是类名,编译器为所有类提供了一个默认的拷贝构造函数。



拷贝构造函数的语法

Classname(const classname & objectname)
{
    . . . .
}

由于它用于创建对象,因此称为构造函数,并且,它还创建了一个新对象,是原对象的拷贝,因此称为拷贝构造函数c++拷贝构造函数

以下是 Copy Constructor 的示例程序:

#include<iostream>
using namespace std;
class Samplecopyconstructor
{
private:
    int x, y;   //成员数据
    
public:
    Samplecopyconstructor(int x1, int y1)
    {
        x = x1;
        y = y1;
    }
    
    /* 拷贝构造函数 */
    Samplecopyconstructor (const Samplecopyconstructor &sam)
    {
        x = sam.x;
        y = sam.y;
    }
    
    void display()
    {
        cout<<x<<" "<<y<<endl;
    }
};
/* 主函数 */
int main()
{
    Samplecopyconstructor obj1(10, 15);     // 一般的构造函数
    Samplecopyconstructor obj2 = obj1;      // 拷贝构造函数
    cout<<"一般的构造函数: ";
    obj1.display();
    cout<<"拷贝构造函数: ";
    obj2.display();
    return 0;
}

以上实例输出结果:

一般的构造函数: 10 15
拷贝构造函数: 10 15


浅拷贝构造函数

通过一个例子来解释浅拷贝构造函数的概念:两名学生正在通过网络共享的两台不同机器,他们同时在 Excel 表中输入他们的详细信息,他们俩所做的更改将反映在excel表中,因为在两个位置都打开了相同的 Excel 表,这就是浅拷贝构造函数中发生的情况,两个对象都将指向相同的内存位置。

浅拷贝只是对原始对象的引用,默认拷贝构造函数提供一个浅拷贝,如下例所示,它是对象的按位复制,当类使用默认拷贝构造函数时,类使用的是浅拷贝,它不会动态分配内存。

c++浅拷贝构造函数

在下面的示例中,你可以看到两个对象 c1 和 c2 都指向相同的内存位置,当 c1.concatenate() 函数被调用时,它也会影响 c2,所以 c1.display()c2.display() 都会给出相同的输出。

#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
    char *s_copy;
public:
    CopyConstructor(const char *str)
    {
        s_copy = new char[16]; // 动态分配内存
        strcpy(s_copy, str);
    }
    /* 连接字符串 */
    void concatenate(const char *str)
    {
        strcat(s_copy, str); //连接两个字符串
    }
    /* 析构函数 */
    ~CopyConstructor ()
    { 
        delete [] s_copy;
    }
    void display()
    {
        cout<<s_copy<<endl;
    }
};

int main()
{
    CopyConstructor c1("Copy");
    CopyConstructor c2 = c1;  // 浅拷贝
    c1.display();
    c2.display();
    c1.concatenate("Constructor");    //c1调用concatenate()
    c1.display();
    c2.display();
    return 0;
}

以上实例输出结果:

Copy
Copy
CopyConstructor
CopyConstructor


深拷贝构造函数

让我们再来看一个深拷贝构造函数的例子:假如你明天要提交作业,时间不够,所以你从朋友那里抄了它,现在你和你的朋友拥有相同的作业内容,但不同的副本,因此,在你的作业副本中所做的任何修改都不会反映在你朋友的副本中,这就是在深拷贝构造函数中发生的事情。

深拷贝会为拷贝的信息分配单独的内存,所以源目标和副本是相互独立的,在一个内存位置所做的任何更改都不会影响另一个位置的副本,当我们使用指针分配动态内存时,我们需要用户定义拷贝构造函数,这两个对象将指向不同的内存位置。

c++深拷贝构造函数

深拷贝的一般要求:

  • 一个普通的构造函数。
  • 一个析构函数来删除动态分配的内存。
  • 一个拷贝构造函数,用于复制动态分配的内存。
  • 一个重载的赋值运算符。

在前面的示例中,你可以看到当 c1 调用 concatenate() 时,c1 和 c2 都发生了变化,因为它们都指向同一个内存位置。

在下面的示例中,你可以看到用户定义的拷贝构造函数,即深拷贝构造函数。这里 c1 和 c2 都指向不同的内存位置,因此,在一个位置所做的更改不会影响另一个位置。

#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
    char *s_copy;
public:
    CopyConstructor (const char *str)
    {
        s_copy = new char[16];  // 动态分配内存
        strcpy(s_copy, str);
    }
    
    CopyConstructor (const CopyConstructor &str)
    {
        s_copy = new char[16]; // 动态分配内存
        strcpy(s_copy, str.s_copy);
    }
    
    void concatenate(const char *str)
    {
        strcat(s_copy, str); // 连接两个字符串
    }

    ~CopyConstructor()
    { 
        delete [] s_copy;
    }

    void display()
    {
        cout<<s_copy<<endl;
    }
};

int main()
{
    CopyConstructor c1("Copy");
    CopyConstructor c2 = c1;    // 拷贝构造函数
    c1.display();
    c2.display();
    c1.concatenate("Constructor");    //c1调用concatenate()
    c1.display();
    c2.display();
    return 0;
}

以上实例输出结果:

Copy
Copy
CopyConstructor
Copy