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

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日

相关文章

  • perl 文件操作总结

    Perl 文件操作总结 文件句柄 在 Perl 中,文件句柄用于与外部文件进行交互。这包括打开、读取和关闭文件。 打开文件 我们可以使用 open 函数打开一个外部文件,并将其指定为一个文件句柄。语法如下: open FILEHANDLE, EXPR 其中 FILEHANDLE 是您打算使用的文件句柄名称,EXPR 是包含您要打开的文件的路径和名称的字符串表…

    other 2023年6月27日
    00
  • Spring Cloud Ribbon 负载均衡使用策略示例详解

    那么下面我将详细讲解“Spring Cloud Ribbon 负载均衡使用策略示例详解”的完整攻略。 一、什么是Spring Cloud Ribbon Spring Cloud Ribbon是一个基于Netflix Ribbon实现的客户端负载均衡的组件,它是Spring Cloud微服务框架的重要组成部分,能够帮助我们轻松地实现服务间的负载均衡。 使用Sp…

    other 2023年6月27日
    00
  • ASP.NET递归法求阶乘解决思路

    ASP.NET递归法求阶乘是利用递归的思想实现阶乘计算的方式。下面是ASP.NET递归法求阶乘的完整攻略: 1. 思路 根据阶乘的定义,n的阶乘可以表示为$n!=n(n-1)(n-2)…1$,所以我们可以利用递归的方式计算阶乘。递归的基本思路是,当计算n的阶乘时,如果n等于1,则返回1;否则,递归计算n-1的阶乘,并将结果与n相乘,得到n的阶乘。 2. …

    other 2023年6月27日
    00
  • MySQL大表中重复字段的高效率查询方法

    针对MySQL大表中重复字段的高效率查询,常见的解决方法包括使用索引或者分库分表等方式,下面我将详细讲解这方面的攻略。 索引优化 使用索引是提高MySQL查询效率的常用方法,对于大表中的重复字段尤其有效。在使用索引时,我们需要注意如下几点: 对于经常查询的字段,建议使用单独的索引,避免创建复合索引。 对于varchar类型的字段,建议指定长度。例如,如果某字…

    other 2023年6月25日
    00
  • docker部署springboot和vue项目的实现步骤

    下面是Docker部署Spring Boot和Vue.js的实现步骤的完整攻略。 1. Docker安装 首先,需要在目标机器上安装Docker。可以参考Docker官方文档进行安装。 参考示例: # Ubuntu 18.04 LTS下安装Docker sudo apt update sudo apt install docker.io # 启动Docker…

    other 2023年6月27日
    00
  • oracle中将clob字段转换成字符串

    Oracle中将CLOB字段转换成字符串 在Oracle数据库中,CLOB(Character Large OBject)是一种用于存储大量字符数据的数据类型。CLOB类型的字段可以存储很大的文本、XML或图像数据,但是与VARCHAR2或RAW类型的数据不同,CLOB类型的数据不支持直接使用=或<>这类操作符进行比较操作。在很多时候,我们需要将…

    其他 2023年3月28日
    00
  • 一分钟掌握linux系统目录结构

    下面是关于“一分钟掌握linux系统目录结构”的完整攻略: 目录结构 Linux系统是基于一个根目录来组织所有的文件和目录的,这个根目录被称为根文件系统(root filesystem)或简称根(/)。Linux的目录结构非常有特色,采用了层次化的结构。 Linux的所有文件和目录都被组织在一个由根目录开头的层次结构下。根据约定,根目录以下的目录大致可以分为…

    other 2023年6月27日
    00
  • 电脑磁盘空间不足怎么办?有什么好的解决方法

    电脑磁盘空间不足的解决方法 当你的电脑磁盘空间不足时,可以采取以下措施来解决这个问题。下面是一个详细的攻略,包含了两个示例说明。 1. 清理磁盘空间 清理磁盘空间是解决电脑磁盘空间不足问题的第一步。你可以通过以下方法来清理磁盘空间: 删除不必要的文件和程序:浏览你的电脑,找到不再需要的文件和程序,并将其删除。这些文件可能包括旧的下载文件、临时文件、垃圾桶中的…

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