深入C++中构造函数、拷贝构造函数、赋值操作符、析构函数的调用过程总结

以下是深入C++中构造函数、拷贝构造函数、赋值操作符、析构函数的调用过程总结:

构造函数的调用过程

  • 当一个对象被创建的时候,其构造函数会被自动调用;
  • 如果该类没有定义构造函数,则系统会为该类自动生成一个默认构造函数;
  • 如果该类存在构造函数,则必须在用户的代码中显式地调用构造函数;
  • 如果一个类有多个构造函数,则在创建对象时可以根据需要选择其中之一来使用;
  • 构造函数调用顺序为:基类先于派生类,而成员对象的初始化顺序则是它们在类定义中出现的顺序。
#include <iostream>

using namespace std;

class Person {
public:
    Person() {
        cout << "调用了默认构造函数" << endl;
    }

    Person(int age) {
        cout << "调用了带参数的构造函数" << endl;
    }
};

int main() {
    Person p1;      // 调用默认构造函数,输出:调用了默认构造函数
    Person p2(20);  // 调用带参数的构造函数,输出:调用了带参数的构造函数
    return 0;
}

拷贝构造函数的调用过程

  • 当使用一个已经存在的对象去初始化同类对象时,将会调用拷贝构造函数。对象可以直接作为参数传递给函数或从函数中返回时,也会调用拷贝构造函数;
  • 如果该类没有定义拷贝构造函数,则系统会为该类自动生成一个默认拷贝构造函数;
  • 自定义的拷贝构造函数需要将传入的对象的属性值复制到新创建的对象中;
  • 如果一个类有多个构造函数,则在创建对象时可以根据需要选择其中之一来使用。
#include<iostream>
using namespace std;
class Person {
public:
    int age;
    char *name;
    Person() : age(0), name(NULL) {
        cout << "默认构造函数被调用" << endl;
    }
    Person(int age_, char *name_) : age(age_), name(name_) {
        cout << "带参数的构造函数被调用" << endl;
    }
    Person(const Person &p) {
        cout << "拷贝构造函数被调用" << endl;
        this->age = p.age;
        // 复制字符串时需要开辟新的存储空间,保证不会影响原对象
        if (p.name != NULL) {
            this->name = new char[strlen(p.name) + 1];
            strcpy(this->name, p.name);
        }
    }
    ~Person() {
        cout << "析构函数被调用" << endl;
        if (name != NULL) { delete[]name; }
    }
};
void print(const Person& p) {
    cout << "Person age: " << p.age << ", name: " << p.name << endl;
}
int main() {
    Person p1(20, "Tom"); // 调用带参数构造函数
    print(p1);
    Person p2(p1);        // 调用拷贝构造函数
    print(p2);
    return 0;
}

赋值操作符的调用过程

  • 当用一个对象去初始化另一个同类对象时会调用拷贝构造函数,但是当对象之间发生赋值操作时,则会调用赋值操作符;
  • 如果该类没有定义赋值操作符,则系统会为该类自动生成一个默认赋值操作符;
  • 自定义的赋值操作符需要将传入的对象的属性值复制到当前对象中,同时防止出现自赋值的情况,即判断传入的对象是否是当前对象。
#include<iostream>
using namespace std;
class Person {
public:
    int age;
    char *name;
    Person() : age(0), name(NULL) {
        cout << "默认构造函数被调用" << endl;
    }
    Person(int age_, char *name_) : age(age_), name(name_) {
        cout << "带参数的构造函数被调用" << endl;
    }
    Person(const Person &p) {
        cout << "拷贝构造函数被调用" << endl;
        this->age = p.age;
        // 复制字符串时需要开辟新的存储空间,保证不会影响原对象
        if (p.name != NULL) {
            this->name = new char[strlen(p.name) + 1];
            strcpy(this->name, p.name);
        }
    }
    ~Person() {
        cout << "析构函数被调用" << endl;
        if (name != NULL) { delete[]name; }
    }
    Person operator=(const Person &p) {
        cout << "赋值操作符被调用" << endl;
        if (this == &p) { // 自赋值的判断
            return *this;
        }
        this->age = p.age;
        if (this->name != NULL) { delete[]name; } // 先删除当前对象中已有的字符串变量
        if (p.name != NULL) { // 复制字符串并开辟新的存储空间
            this->name = new char[strlen(p.name) + 1];
            strcpy(this->name, p.name);
        }
        return *this;
    }
};
void print(const Person& p) {
    cout << "Person age: " << p.age << ", name: " << p.name << endl;
}
int main() {
    Person p1(20, "Tom"); // 调用带参数构造函数
    print(p1);
    Person p2;        // 调用默认构造函数
    p2 = p1;          // 调用赋值操作符函数
    print(p2);
    return 0;
}

析构函数的调用过程

  • 对象在销毁时,系统会自动调用其析构函数;
  • 当对象为局部自动对象时,程序在此对象的作用域结束时会自动调用其析构函数;
  • 如果该类没有定义析构函数,则系统会为该类自动生成一个默认析构函数;
  • 自定义的析构函数需要释放对象在创建过程中所占用的动态分配的内存空间。
#include<iostream>
using namespace std;
class Person {
public:
    Person() {
        cout << "默认构造函数被调用" << endl;
    }
    ~Person() {
        cout << "析构函数被调用" << endl;
    }
};
int main() {
    Person p; // 调用默认构造函数
    return 0; // 调用析构函数
}

以上就是深入C++中构造函数、拷贝构造函数、赋值操作符、析构函数的调用过程总结的攻略,我们可以看到,构造函数,拷贝构造函数,赋值操作符以及析构函数都是类的重要组成部分,它们的正确使用对于保证程序的稳定性非常重要。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入C++中构造函数、拷贝构造函数、赋值操作符、析构函数的调用过程总结 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • Node.js处理I/O数据之使用Buffer模块缓冲数据

    Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它能够在服务器端解析 JavaScript代码,同时具有高效的I/O操作能力。其中,Buffer模块是Node.js核心库中处理二进制数据的工具之一。我们可以使用Buffer模块来创建缓冲区,对数据进行读写操作。 创建Buffer 我们可以使用以下方法来创建Buffer实例: co…

    C 2023年5月23日
    00
  • C++超集C++/CLI模块的基本语法

    C++/CLI是一个能够在.NET Framework下,基于C++语言创建托管代码的技术。C++/CLI模块是指一个.dll文件,它包含用C++/CLI语法写的代码,能够被.NET程序引用并利用其中的类、方法等等。 C++/CLI模块的基本语法如下: 命名空间(namespace) C++/CLI和C++一样可以使用命名空间(namespace)来整理代码…

    C 2023年5月22日
    00
  • C程序 检查两个矩阵是否相等

    下面我将详细讲解如何使用“C程序 检查两个矩阵是否相等”。 什么是“C程序 检查两个矩阵是否相等” “C程序 检查两个矩阵是否相等”是一段使用C语言编写的程序,可以用来检查两个矩阵是否相等。它可以判断两个矩阵是否具有相同的行列数,并逐一比较矩阵中的每一个元素,以判断两个矩阵是否相等。 如何使用“C程序 检查两个矩阵是否相等” 要使用“C程序 检查两个矩阵是否…

    C 2023年5月9日
    00
  • c++编写String类代码实例

    下面是详细讲解”C++编写String类代码实例”的攻略: 1. 什么是String类? String类是C++中封装了的字符串类,它提供了很多操作字符串的方法,如获取字符串长度、复制字符串、连接字符串、比较字符串等等。使用String类可以大大简化字符串操作的过程,提高代码可读性和可维护性。 2. String类的基本实现 2.1 类的定义 class S…

    C 2023年5月24日
    00
  • 神舟K570C怎么样?神舟精盾K570C笔记本评测图文详细介绍

    神舟K570C笔记本评测 神舟K570C是一款高性能笔记本电脑,它被广泛应用于办公和娱乐等方面。本篇文章将从外观、配置、性能等多个方面来介绍神舟K570C。 外观 神舟K570C采用了一款黑色金属材质,整体风格简约大气,手感舒适,具有一定的耐磨性。机身较为轻薄,采用14英寸的IPS屏幕,分辨率为1920*1080。键盘布局合理,手感柔软,背光灯的设计让用户在…

    C 2023年5月23日
    00
  • C++线程中几类锁的详解

    C++线程中几类锁的详解 前言 在多线程编程中,锁是一种重要的同步机制,可以保证多个线程在访问共享资源时的安全性。C++提供了多种类型的锁,本篇文章将对常用的几种锁进行详解。 互斥锁(mutex) 互斥锁是最常用的一种锁,它保证同一时刻只有一个线程可以访问共享资源。当一个线程获得锁时,其他线程将一直等待直到拥有锁的线程释放锁为止。 创建互斥锁 C++标准库提…

    C 2023年5月22日
    00
  • Vue渲染失败的几种原因及解决方案

    下面是“Vue渲染失败的几种原因及解决方案”的完整攻略。 1. 原因 1.1 HTML标签错误 在使用Vue渲染模板时,如果HTML标签结构错误,Vue可能会无法解析。常见的原因是HTML标签未闭合或嵌套顺序不正确。 1.2 数据类型不匹配 当Vue在渲染模板时,如果数据类型与模板中的期望不匹配,Vue也可能会渲染失败。例如,模板中期望传入一个字符串,但实际…

    C 2023年5月23日
    00
  • Clion配置opencv开发环境的详细过程

    Clion配置opencv开发环境的详细过程 在Clion中使用OpenCV需要进行相关的配置,以下是Clion配置OpenCV开发环境的详细过程: 步骤一: 安装OpenCV 首先,需要在本地安装OpenCV。 在Linux系统中,可以通过以下命令快速安装OpenCV: sudo apt-get install libopencv-dev 在Windows…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部