【面向对象】构造函数与析构函数详解

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

构造函数与析构函数详解

在这里插入图片描述


文章目录


😊点此到文末惊喜↩︎

构造函数

类型

  1. 默认构造函数缺省构造函数
    • 一个类中只能出现一个默认构造函数
    • 在调用时不需要传入实参。因为默认构造函数通常是无参的或所有形参都有缺省值
    • 使用默认构造函数的时候创建对象不能后面带有括号
    • 编译器自动生成non-trivial的构造函数有四种情况其他情况就算编译器产生了默认构造函数也没有实质作用。
      • 类中有类类A含有类B的对象作为成员并且类B显式定义了默认构造函数则定义类A对象的时候编译器会产生一个默认构造函数并在这个默认构造函数中提供了调用类B构造函数的代码。
      • 类继承类类B继承于类A且类A显式定义了构造函数那么在生成类B对象的过程中编译器同样会产生一个默认构造函数在这个构造函数中提供调用基类A构造函数的代码
      • 含虚函数类某个类含有虚函数那么编译器会自动产生一个默认构造函数以提供虚表指针相关的初始化操作
      • 虚继承基类一个类虚继承于其他类那么同样的编译器会为该类产生默认的构造函数。
  2. 初始化构造函数有参构造函数
    • 在创建对象时使用实参为对象的成员属性赋值由编译器自动调用
  3. 复制 / 拷贝构造函数
    • 若没有显示定义复制构造函数则系统会默认创建一个复制构造函数当类中有指针成员时由系统默认创建的复制构造函数会存在“浅拷贝”的风险因此必须显示定义复制构造函数。
    • 复制构造函数参数为类对象本身的引用根据调用对象进行深拷贝构建实参对象
    • 被调用的三种情况
      • 对象用于给其他对象进行赋值初始化
      • 对象作为函数形参
      • 对象作为函数返回值实质是返回值对象作为类复制构造函数实参而调用
      //  1. 对象的赋值初始化
      Complex c2(c1);
      Complex c2 = c1;
      // 2. 函数形参
      void Function(Complex  c){
      	 ...
      }
      	// 可以使用const & 确保实参的值不会改变并避免复制构造函数带来的深拷贝开销
      void Function(const Complex & c){
      	 
      }
      //3. 函数返回值
      Complex Func() {
          Complex  a(4);
          return a;
      }
      
  4. 移动构造函数
    • 临时对象转移内存所属权时调用使用右值引用作为参数。
    	class Integer {
    	private:
    	    int* m_ptr;
    	public:
    		Integer(Integer&& source)// 注意形参是右值引用
    		  : m_ptr(source.m_ptr) {
    		    source.m_ptr= nullptr;
    		    cout << "Call Integer(Integer&& source)移动" << endl;
    		}
    	};
    	int main(int argc, char const* argv[]) {
    	    Integer a;
    	    Integer b(std::move(a));// 将a转换成右值引用
    	    return 0;
    	}
    
  5. 委托构造函数
    • 构造函数可以在同一个类中一个构造函数调用另一个构造函数从而达到简化代码的目的。
    #include <iostream>
    class Base 
    {
    public:
    	int value1;
    	int value2;
    	Base()    //目标构造函数
    	{
    		value1 = 1;
    	}
    	Base(int value) : Base()  //委托构造函数
    	{ // 委托 Base() 构造函数
    		value2 = value;
    	}
    };
    void EntrustedConstruction()
    {
    	Base b(2);  //首先调用Base(int value) : Base() 毫无疑问
        //然后会走到base()中先给value1复制然后走到Base(int value) : Base() 给value2赋值
    	std::cout << b.value1 << std::endl;
    	std::cout << b.value2 << std::endl;
    }
    
    
  6. 转换构造函数
    • 只有一个参数的构造函数而且该参数又不是本类的const引用
    	#include <iostream>
    using namespace std;
    
    class Student{
    public:
        //1. 默认构造函数没有参数或形参具有缺省值
        Student(int i=2){
            this->age = 20;
            this->num = 1000;
        };  
        // 2. 初始化构造函数有参数和参数列表
        Student(int a, int n):age(a), num(n){};
        // 3. 拷贝构造函数参数是对象
        Student(const Student& s){
            this->age = s.age;
            this->num = s.num;
        };
        // 4. 移动构造函数参数是右值引用
        Student(const Student&& s){
            this->age = s.age;
            this->num = s.num;
        }; 
        
        // 3. 转换构造函数形参是其他类型变量且只有一个形参
        Student(int r){   //
            this->age = r;
    		this->num = 1002;
        };
        ~Student(){}
    public:
        int age;
        int num;
    };
    


少年我观你骨骼清奇颖悟绝伦必成人中龙凤。
秘籍点击图中书籍·有缘·赠予你


🚩点此跳转到首行↩︎

参考博客

  1. C++构造函数之默认构造函数
  2. C++默认构造函数——深入理解
  3. 对C++默认构造函数的一点重要说明
  4. 拷贝构造函数
  5. 委托构造函数详解小白也可以看懂
  6. 待定引用
  7. 待定引用
  8. 待定引用
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6