【C++】构造函数和析构函数

构造函数 Constructor

也叫构造器,再对象创建的时候自动调用,一般用于完成对象的初始化工作。

struct Person {
    int m_age;
    Person() {
        m_age = 0;
        cout << "Person()" << endl;
    }    
    Person(int age) {
        m_age = age;
        cout << "Person(int age)" << endl;
    }
};

特点:

  • 函数名与类同名,无返回值(void都不能写),可以有参数,可以重载,可以有多个构造函数。
  • 一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象

注意:

  • malloc分配的对象不会调用构造函数

    struct Person {
        int m_age; 
        Person() {  
            cout << "Person()" << endl; 
        } 
        void run() {   
            cout << "run() - " << m_age << endl; 
        }
    };
    // 定义在全局区,可以调用构造函数
    Person g_person;
    int main() {  
        Person person1; 
        // 定义在栈空间,可以调用构造函数    
        Person *p = new Person; 
        // 定义在堆空间,可以调用构造函数    
        delete p;       
        Person *p = (Person *) malloc(sizeof(Person)); 
        p->m_age = 10;  
        p->run();   
        // 运行结果是:  
        // run() - 10  
        // 并没有调用构造函数   
        free();
    }
    

    如果要将对象放在堆空间,一定用 new 不要用 malloc

    默认情况下,编译器会为每一个类生成空的无参的构造函数

    修正:在某些特定的情况下,编译器才会为类生成空的无参的构造函数

  • 关于构造函数的调用!

    struct Person { 
        int m_age;     
        Person() {     
            m_age = 0;  
            cout << "Person()" << endl;   
        }  
        Person(int age) {   
            m_age = age;    
            cout << "Person(int age)" << endl;  
        }
    };
    Person g_person0; 		
    // Person()
    Person g_person1(); 	
    // 函数声明
    Person g_person2(10); 	
    // Person(int age)
    int main() {   
        Person person0; 	
        // Person() 
        Person person1();	
        // 函数声明   
        Person person2(20); 	
        // Person(int age)    
        Person *p0 = new Person; 
        // Person()  
        Person *p1 = new Person(); 	
        // Person()   
        Person *p2 = new Person(30); 
        // Person(int age)      
        getchar();   
        return 0;
    }
    

    表面上来看一共调用了9次对象,其中3次是传入参数的,输出应该有6个Person(),3个Person(int age)

    但实际上只有4个Person(),3个Person(int age)

    因为 Person g_person1()Person person1()函数声明,并非调用构造函数!!!

  • 成员变量的初始化

    // 全局区:成员变量初始化为0
    Person g_person;
    int main() {   
        // 栈空间:没有初始化成员变量  
        // Person person; 直接写会报错    
        // 堆空间:没有初始化成员变量,输出 -842150451  
        Person *p0 = new Person;  
        // 堆空间:成员变量初始化为0  
        Person *p1 = new Person();
    }
    

    但如果在类里加一个空的构造函数

    struct Person {  
        int m_age; 
        Person() { 
        }
    };
    // 全局区:成员变量初始化为0
    Person g_person; 
    int main() { 
        // 栈空间:没有初始化成员变量 
        // Person person; 直接写会报错    
        // 堆空间:没有初始化成员变量,输出 -842150451
        Person *p0 = new Person;  
        // 堆空间:不再会自动初始化成员变量,输出 -842150451 
        Person *p1 = new Person();
    }
    
    • 结论:如果自定义了构造函数,除了全局区,其他内存空间的成员变量默认都不会初始化,需要开发人员手动初始化

析构函数 Destructor

在对象销毁的时候自动调用,一般用于完成对象的清理工作,避免内存泄漏(该释放的内存没有得到释放)。

struct Person {  
    int m_age;   
    // 新的Person对象诞生的象征 
    Person() {      
        cout << "Person::Person()" << endl;  
    }   
    // 一个Person对象销毁的象征   
    ~Person() {   
        cout << "~Person()" << endl; 
    }
};
void test() {  
    Person person;
}
int main() {  
    cout << "1" << endl;  
    test();  
    cout << "2" << endl;
    getchar();
    return 0;
}
// 输出
// 1
// Person::Person()
// ~Person()
// 2
  • 特点

    函数名以~开头,与类同名,无返回值,无参,不可以重载,有且只有一个析构函数。

  • 注意

    • 通过 malloc 分配的对象 free 的时候不会调用析构函数。

    • class 中构造函数、析构函数要声明为 public 才能被外界正常使用。

    • 对象内部申请的堆空间,由对象内部回收

      struct Car {   
          int m_price;  
          Car() {     
              cout << "Car::Car()" << endl;
          }  
          ~Car() { 
              cout << "~Car()" << endl;    
          }
      };
      struct Person { 
          int m_age;  
          Car *m_car;     
          Person() {     
              m_age = 0;   
              m_car = new Car();   
              cout << "Person::Person()" << endl;   
          }   
          ~Person() {      
              delete m_car; 	
              // 需要再将m_car在堆空间的内存手动释放     
              cout << "~Person()" << endl; 
          }
      };
      int main() {  
          {   
              Person person; 
          }  
          getchar(); 
          return 0;
      }
      

在这里插入图片描述

如果不在person的析构函数中加`delete m_car;`的话

Person会析构,car不会析构。需要在main函数手动释放,封装性不强。

- 都在栈空间

  ```C++
  struct Car {
      int m_price;
  };
  struct Person { 
      int m_age;
      Car *m_car;
  };
  Person p;
  ```

在这里插入图片描述

  • 都在堆空间

    在这里插入图片描述

    struct Car {  
        int m_price;
    };
    struct Person {
        int m_age; 
        Car *m_car;
    };
    Person *p = new Person();
    

    在这里插入图片描述

    struct Car { 
        int m_price;
    };
    struct Person { 
        int m_age;
        Car *m_car;   
        Person() { 
            m_car = new Car();  
        }    
        ~Person() {
            delete m_car; 
        }
    };
    Person *p = new Person();
    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值