c++之對象的初始化和清理


在生活中我們購買單電子產品通常都會有出廠設置,在某一天我們不用也會刪除一些自己的數據信息以保證安全。

c++中的面向對象來源於生活,每個對象也都會有初始設置以及對象銷毀清理數據的設置。

1.構造函數和析構函數

對象的初始化和清理也是兩個非常重要的安全問題:

  • 一個對象或者變量沒有初始狀態,對其使用后結果未知。
  • 同樣的使用完一個對象或者變量,沒有及時清理,也會造成一定的安全問題。

c++利用了構造函數和析構函數解決上述問題,這兩個函數將會被編譯器自動調用,完成對象初始化和清理工作。對象的初始化和清理工作是編譯器強制我們做的事情,因此如果我們不提供構造函數和析構函數,編譯器會提供編譯器提供的構造函數和析構函數的空實現。

什么是構造函數?

主要作用於創建對象時為對象的成員屬性進行賦值。

什么是析構函數?

主要作用於對象在銷毀時執行一些清理工作。

構造函數語法:類名(){}

  • 構造函數,沒有返回值也不寫void
  • 函數名與類名相同
  • 構造函數可以有參數,因此可以重載
  • 程序在創建對象時會自動調用構造函數,而且只會調用一次

析構函數語法:~類名(){}

  • 析構函數,沒有返回值也不寫void
  • 函數名與類名相同,在名稱前面jiahsang~
  • 構造函數不可以有參數,因此不能重載
  • 程序在對象銷毀時會自動調用析構函數,而且只會調用一次
#include<iostream>
using namespace std;

class Student {
    string name;
    int age;
    double score;
public:
    //構造函數
    Student(){
        cout << "調用構造函數" << endl;
    }
    //析構函數
    ~Student() {
        cout << "調用析構函數" << endl;
    }
};

void test() {
    //在棧上的數據,test執行完畢之后就會被釋放
    Student s;
}

int main() {
    test();
    system("pause");
    return 0;
}

2.構造函數的分類以及調用

兩種分類方式:有參構造、無參構造;普通構造、拷貝構造;

三種調用方式:括號法、顯示法、隱式替換法;

#include<iostream>
using namespace std;

class Student {
    string name;
    int age;
    double score;
public:
    //無參構造函數
    Student(){
        cout << "調用Student()構造函數" << endl;
    }
    //有參構造函數
    Student(string name,int age) {
        cout << "調用Student(string name,int age)構造函數" << endl;
    }
    //拷貝構造函數
    Student(const Student &stu) {
        name = stu.name;
        age = stu.age;
        score = stu.score;
        cout << "調用拷貝構造函數" << endl;
    }
    //析構函數
    ~Student() {
        cout << "調用Student()析構函數" << endl;
    }
};

void test() {
    //匿名對象,當前行運行完后就會調用析構函數
    //不要使用拷貝構造函數初始化匿名對象:Student(s2);
    Student();
    //隱式三種形式
    cout << "隱式調用" << endl;
    Student s1;
    Student s2{"tom",12};
    Student s3{ s2 };
    //顯示三種形式
    cout << "顯示調用" << endl;
    Student s4 = Student();
    Student s5 = Student("bo",22);
    Student s6 = Student(s5);
    //隱式轉換法,相當於Student s7 = Student{ "mike",17 };
    Student s7 = { "mike",17 };

}

int main() {
    test();
    system("pause");
    return 0;
}

輸出:

 

 

3.拷貝構造函數的調用時機

c++拷貝構造函數調用時有三種情況

  • 使用一個已經創建完畢的對象來初始化一個新對象;
  • 值傳遞的方式給函數參數傳輸;
  • 以值方式返回局部對象; 

即這三種情況下都會調用拷貝構造函數。

#include<iostream>
using namespace std;

class Person {
public:
    int m_age;
public:
    Person() {
        cout << "Person默認構造函數" << endl;
    }
    Person(int age) {
        m_age = age;
        cout << "Person(int age)構造函數" << endl;
    }
    Person(const Person& p) {
        m_age = p.m_age;
        cout << "拷貝構造函數" << endl;
    }
    ~Person() {
        cout << "Person析構函數" << endl;
    }
};

//使用一個已經創建完畢的對象來初始化一個新對象
void test() {
    Person p1(22);
    Person p2(p1);
    cout << "p2的年齡是:" << p2.m_age << endl;
}
void doWork(Person p) {}
//使用值傳遞的方式
void test2() {
    Person p;
    doWork(p);
}
//值返回局部對象
Person doWork2() {
    Person p1;
    return p1;
}
void test3() {
    Person p = doWork2();
}

int main() {
    test3();
    system("pause");
    return 0;
}

4.構造函數的調用規則

默認情況下,c++編譯器至少會給一個類添加三個函數

  • 默認無參構造函數
  • 默認析構函數;
  • 默認拷貝構造函數,對屬性進行值拷貝;

構造函數調用規則如下

  • 如果用戶自定義構造函數,c++不再提供無參構造函數,但是會提供拷貝構造函數;
  • 如果用戶自定義拷貝構造函數,c++不會再提供其它構造函數;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM