C++超详细讲解拷贝构造函数

yizhihongxing

C++超详细讲解拷贝构造函数

什么是拷贝构造函数

C++中的拷贝构造函数是一种特殊的构造函数,用于关于同类对象进行复制初始化。当使用一个对象去初始化另一个同类对象时,就会调用拷贝构造函数。拷贝构造函数通常使用一个类的引用作为其参数,并且不允许传入除该引用以外的任何值。

拷贝构造函数的使用场景

  1. 传递类对象给函数时,会调用拷贝构造函数;
  2. 返回类对象时,会调用拷贝构造函数;
  3. 在类中对当前类对象生成一个副本时,会调用拷贝构造函数。

拷贝构造函数示例1:深拷贝

在以下示例中,我们定义了一个学生类,并定义了两个对象stu1和stu2。在stu1作为参数传递给函数print()时,会调用一次拷贝构造函数。由于没有定义自己的拷贝构造函数,所以系统自动提供了一个默认的拷贝构造函数——进行逐个赋值;在函数print()中,我们输出了相应的学生信息。在运行过程中,我们可以看到两个对象的信息都被成功地输出。

#include <iostream>
#include <string>

using namespace std;

class Student
{
public:
    Student(string name, int age, int* scores);
    Student(const Student& stu);    // 拷贝构造函数
    void print();
    ~Student();
private:
    string name;
    int age;
    int* scores;
};

Student::Student(string name, int age, int* scores)
{
    this->name = name;
    this->age = age;
    this->scores = new int[3];
    for (int i = 0; i < 3; i++)
    {
        this->scores[i] = scores[i];
    }
}

Student::Student(const Student& stu)    // 拷贝构造函数
{
    this->name = stu.name;
    this->age = stu.age;
    this->scores = new int[3];
    for (int i = 0; i < 3; i++)
    {
        this->scores[i] = stu.scores[i];
    }
}

void Student::print()
{
    cout << "Name: " << this->name << endl;
    cout << "Age: " << this->age << endl;
    cout << "Scores: ";
    for (int i = 0; i < 3; i++)
    {
        cout << this->scores[i] << " ";
    }
    cout << endl;
}

Student::~Student()
{
    if (this->scores)
    {
        delete[] this->scores;
    }
} 

void print(Student stu)
{
    cout << "Print a Student object: " << endl;
    stu.print();
}

int main()
{
    int scores[3] = {90, 80, 70};
    Student stu1("Tom", 18, scores);
    Student stu2 = stu1;    // 调用一次拷贝构造函数
    stu2.print();
    print(stu1);    // 调用一次拷贝构造函数
    return 0;
}

拷贝构造函数示例2:浅拷贝

在以下示例中,我们定义了一个沙漏类,并定义了两个对象Hourglass1和Hourglass2,其中Hourglass1的high属性指向一个动态分配的int型变量,并在析构函数中释放空间,而Hourglass2则是Hourglass1的复制。由于没有自定义的拷贝构造函数来完成深拷贝,因此默认的拷贝构造函数将进行浅拷贝,即直接将指针复制过去,导致两个对象共享同一块内存空间。在释放Hourglass2时,由于析构函数会先释放这块空间,而当再次释放Hourglass1时,程序因为重复释放内存空间而抛出异常。

#include<iostream> 
#include<cstring> 

using namespace std;

class Hourglass
{
public:
    Hourglass(int myHigh = 10); 
    Hourglass(const Hourglass& hg); // 拷贝构造函数
    ~Hourglass(); 
    void PrintHourGlassHeight(); 
private:
    int high; 
    int* low; 
};

Hourglass::Hourglass(int myHigh) 
{ 
    high = myHigh; 
    low = new int[high]; 
    memset(low, 0, sizeof(int) * high); 
} 

Hourglass::~Hourglass()
{
    delete[] low;
    cout << "Release Hourglass memory successfully!" << endl;
}

Hourglass::Hourglass(const Hourglass& hg) // 拷贝构造函数
{
    high = hg.high;
    low = hg.low;
}

void Hourglass::PrintHourGlassHeight()
{
    cout << "The high of the Hourglass: " << high << endl;
}

int main()
{
    Hourglass Hourglass1;
    Hourglass Hourglass2(Hourglass1);    // 调用一次拷贝构造函数
    Hourglass2.PrintHourGlassHeight();
    return 0;
}

总结

C++中的拷贝构造函数是一种特殊的构造函数,用于关于同类对象进行复制初始化。适当地使用拷贝构造函数可以避免问题出现,但若不谨慎使用则可能会造成内存空间重复释放的问题。在使用时,需要考虑数据的类型、数据的大小等多方面的因素,针对性地选择不同的拷贝构造函数实现方式。

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

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

相关文章

  • 魔兽世界7.25射击猎输出手法一览 射击猎输出手法及技能循环介绍

    魔兽世界7.25射击猎输出手法一览 本篇攻略将详细介绍魔兽世界7.25版本中射击猎人的输出手法及技能循环,帮助玩家更好地掌握射击猎人的输出能力。 射击猎输出手法及技能循环介绍 射击猎人的输出手法及技能循环包括以下几个方面: 1. 暴击率优先 在射击猎输出中,暴击率是最重要的因素之一。建议射击猎珍视暴击率,通过技能循环和裝備提高暴击率以达到更高的伤害输出。 2…

    other 2023年6月27日
    00
  • Java通过python命令执行DataX任务的实例

    前置条件和说明: 本攻略适用于Linux、MacOS等类Unix操作系统; Java应用程序需要运行在JRE 1.8以上的环境中; Python需要安装3.x版本。 实现步骤: 2.1 下载DataX 首先需要在自己的电脑中下载DataX,可以从DataX官方Github仓库的releases页面下载最新的DataX压缩包。 例如,在终端中使用wget命令下…

    other 2023年6月27日
    00
  • 从数据类型 varchar 转换为 numeric 时出错.

    从数据类型 varchar 转换为 numeric 时出错 在使用 SQL 语句查询数据时,我们经常需要进行数据类型转换。其中一种常见的转换是将文本类型(varchar)转换为数字类型(numeric)。然而,即使两种类型的数据在外观上看起来相似,进行类型转换时仍可能会出现错误。 错误信息 当我们尝试将一个 varchar 类型的字符串转换为 numeric…

    其他 2023年3月28日
    00
  • Android实现可滑动的自定义日历控件

    Android实现可滑动的自定义日历控件攻略 1. 概述 在Android中实现可滑动的自定义日历控件可以提供用户友好的日历浏览体验。本攻略将介绍一种实现方法,使用RecyclerView和自定义Adapter来展示日历,并通过手势监听实现滑动功能。 2. 步骤 2.1 创建项目和布局文件 首先,创建一个新的Android项目,并在布局文件中添加一个Recy…

    other 2023年9月6日
    00
  • 深入解析Java编程中的抽象类

    深入解析Java编程中的抽象类 概念 在 Java 编程中,抽象类是一种不能被实例化的类,只能被继承,且其继承的子类必须实现抽象类中定义的抽象方法。抽象类通常被用来建模一种需求或者概念,以便多个子类可以对其进行具体的实现。 如何定义抽象类 使用 abstract 关键字来定义抽象类,抽象类中可以包含抽象方法、非抽象方法、成员变量和构造函数等成员。其中,抽象方…

    other 2023年6月26日
    00
  • windows server 2019 服务器搭建的方法步骤(图文)

    以下是详细讲解“windows server 2019 服务器搭建的方法步骤(图文)”的完整攻略,过程中包含两条示例说明。 1. 准备工作 在搭建Windows Server 2019服务器之前,我们需要做一些准备工作: 一台符合以下要求的电脑: 64位处理器 支持物理内存至少为2GB 支持512MB以上的可用系统存储器 支持网卡并至少具备传输速率为1Gbp…

    other 2023年6月27日
    00
  • HTML5标签嵌套规则详解【必看】

    HTML5标签嵌套规则详解【必看】攻略 HTML5标签嵌套规则是指在HTML文档中,各个标签之间的嵌套关系必须符合一定的规则。这些规则有助于确保HTML文档的结构清晰、语义明确,并且能够正确地被浏览器解析和渲染。下面是HTML5标签嵌套规则的详细讲解。 1. 嵌套规则的基本原则 标签必须按照正确的层次结构进行嵌套,即一个标签可以包含其他标签,但不能交叉嵌套或…

    other 2023年7月27日
    00
  • JUnit 5中扩展模型的深入理解

    JUnit 5中扩展模型的深入理解 JUnit 5是一个流行的Java测试框架。JUnit 5的一个主要特点是其扩展模型,该模型允许用户编写自己的扩展以定制测试框架的行为。本文将探讨JUnit 5中扩展模型的深入理解。我们将讨论以下主题: 扩展模型的概念和工作原理 编写扩展以定制测试框架的行为 扩展示例 扩展模型的概念和工作原理 JUnit 5通过“扩展”来…

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