深入C++拷贝构造函数的总结详解

深入C++拷贝构造函数的总结详解

什么是拷贝构造函数

在 C++ 中,每个类都有至少一个构造函数,负责创建这个类的对象。其中,拷贝构造函数是一种特殊的构造函数,它负责用一个已经存在的对象来初始化一个新的对象。拷贝构造函数的原型为:

类名(const 类名 &obj)

其中,obj 是需要拷贝的对象的引用。

拷贝构造函数的调用时机

当一个对象需要复制到另一个对象时,就会调用该对象的拷贝构造函数。具体包括以下情况:

  1. 当一个对象作为另一个对象的实参进行传递时,拷贝构造函数会被调用。
  2. 当一个对象作为函数返回值进行返回时,拷贝构造函数会被调用。
  3. 当一个对象被另一个对象进行初始化时,拷贝构造函数会被调用。

浅拷贝和深拷贝

拷贝构造函数的实现方式有两种,分别是浅拷贝和深拷贝。它们的区别在于如何复制对象的成员变量。

浅拷贝

浅拷贝就是简单地将源对象的成员变量复制到目标对象中。如果源对象中某个成员变量是一个指针,那么目标对象中的该成员变量将指向与源对象中相同的内存地址。由于两个对象共享同一块内存,因此当其中任何一个对象进行内存释放时,另一个对象的指针也将变为悬空指针。

class ShallowCopy {
public:
    int num;
    char* str;
    ShallowCopy(int n, const char* s) {
        num = n;
        str = new char[strlen(s) + 1];
        strcpy(str, s);
    }
    // 浅拷贝构造函数
    ShallowCopy(const ShallowCopy& obj) {
        num = obj.num;
        str = obj.str;
    }
    ~ShallowCopy() {
        delete[] str;
    }
};

int main() {
    ShallowCopy obj1(1, "Hello");
    ShallowCopy obj2 = obj1;
    // 修改 obj1.str 的值
    obj1.str[0] = 'h';
    cout << obj1.str << endl; // hello
    cout << obj2.str << endl; // hello
    return 0;
}

深拷贝

深拷贝则是将源对象的成员变量复制到一个新的内存地址中,并将目标对象的成员变量指向该内存地址。由于目标对象与源对象的成员变量指向不同的内存地址,因此它们彼此独立,互不干扰。

class DeepCopy {
public:
    int num;
    char* str;
    DeepCopy(int n, const char* s) {
        num = n;
        str = new char[strlen(s) + 1];
        strcpy(str, s);
    }
    // 深拷贝构造函数
    DeepCopy(const DeepCopy& obj) {
        num = obj.num;
        str = new char[strlen(obj.str) + 1];
        strcpy(str, obj.str);
    }
    ~DeepCopy() {
        delete[] str;
    }
};

int main() {
    DeepCopy obj1(1, "Hello");
    DeepCopy obj2 = obj1;
    // 修改 obj1.str 的值
    obj1.str[0] = 'h';
    cout << obj1.str << endl; // hello
    cout << obj2.str << endl; // Hello
    return 0;
}

示例说明

上面的示例说明了浅拷贝和深拷贝的区别。我们先定义了一个 ShallowCopy 类和一个 DeepCopy 类,它们都有一个 num 整型成员变量和一个 str 字符串成员变量。其中,ShallowCopy 类的拷贝构造函数实现了浅拷贝,DeepCopy 类的拷贝构造函数实现了深拷贝。

main 函数中,分别定义了 obj1obj2 对象,并将 obj1 的值赋给了 obj2。然后,我们修改了 obj1str 成员变量的值,并输出了 obj1obj2str 成员变量的值。由于 ShallowCopy 类的拷贝构造函数实现了浅拷贝,因此 obj2str 指针指向了 obj1 中的 str 指针,它们共享同一块内存,因此修改了 obj1.str 的值后,obj2.str 的值也发生了相应的变化;而 DeepCopy 类的拷贝构造函数实现了深拷贝,因此 obj2str 成员变量指向了一个新的内存地址,它们彼此独立,互不干扰,因此修改了 obj1.str 的值后,obj2.str 的值没有发生变化。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入C++拷贝构造函数的总结详解 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • 使用post请求下载文件

    使用POST请求下载文件的完整攻略 在Web开发中,有时需要使用POST请求下载文件。以下是使用POST请求下载文件的完整攻略。 步骤1:创建POST请求 首先,需要创建一个POST请求,以便向服务器请求文件。可以使用各种编程语言框架来创建POST请求,例如Python的requests库、Java的HttpURLConnection类等。以下是使用Pyth…

    other 2023年5月8日
    00
  • Android编程之include文件的使用方法

    Android编程之include文件的使用方法攻略 在Android编程中,我们经常会使用include文件来重用布局和视图组件。include文件允许我们在一个布局文件中引用另一个布局文件,从而实现代码的复用和模块化。下面是使用include文件的完整攻略,包含两个示例说明。 步骤一:创建被引用的布局文件 首先,我们需要创建一个被引用的布局文件,即将被重…

    other 2023年8月26日
    00
  • SpringBoot读取Resource下文件的4种方法

    当使用SpringBoot进行开发时,有时候需要读取Resource文件夹下的文件,本文将介绍4种读取Resource下文件的方法。 方法一:使用ClassLoader.getResourceAsStream() ClassLoader.getResourceAsStream()方法可以获取资源在classpath下面的任意资源。如下所示: InputStr…

    other 2023年6月25日
    00
  • Spring Boot 把配置文件和日志文件放到jar外部

    Step 1:创建Spring Boot项目 首先,我们创建一个Spring Boot项目。可以使用Spring Intializr或者自行使用maven创建。这里我们使用Spring Intializr,选择下面的选项: 项目名称:spring-boot-external-config-logs 项目类型:Maven Project 依赖:Spring B…

    other 2023年6月25日
    00
  • 详解Vue项目中出现Loading chunk {n} failed问题的解决方法

    详解Vue项目中出现Loading chunk {n} failed问题的解决方法 在Vue项目开发过程中,有时候会出现“Loading chunk {n} failed”这样的错误提示,导致页面无法正常访问。这种情况通常是由于项目中的JavaScript代码被分割成多个块(chunks)时,某个块无法正确加载导致的。本文将详细讲解此问题的解决方法。 原因分…

    other 2023年6月27日
    00
  • hive创建表

    Hive创建表 Hive是基于Hadoop的一种数据仓库解决方案,它提供了类SQL的接口,可以将结构化的数据映射为一张数据库表,并通过HiveQL查询语言进行数据的分析和查询。下面我们将介绍如何在Hive中创建表。 创建表语法 我们可以使用CREATE TABLE语句在Hive中创建表格,其语法如下: CREATE [EXTERNAL] TABLE [IF …

    其他 2023年3月28日
    00
  • java实现html转pdf的方法

    Java实现HTML转PDF的方法 简介 Java是一种广泛应用的编程语言,由于其平台无关性和强大的生态系统,成为了许多企业和个人实现不同需求的首选之一。本文将介绍如何使用Java实现将HTML转换成PDF。 方案 要将HTML转换成PDF,我们需要借助Java中的第三方库,本文将介绍以下两种常用的方案: 使用iText库 使用Flying Saucer库 …

    其他 2023年3月28日
    00
  • Python 中enum的使用方法总结

    Python 中enum的使用方法总结 1. 引言 在Python中,enum是一个非常有用的模块,它允许我们定义一组具有特定值的常量。使用enum可以提高代码的可读性和可维护性。本文将详细介绍enum的使用方法,并提供两个示例说明。 2. 定义枚举 要使用enum,首先需要导入Enum类。然后,可以通过继承Enum类来定义自己的枚举类型。下面是一个示例: …

    other 2023年8月18日
    00
合作推广
合作推广
分享本页
返回顶部