1. 程式人生 > 其它 >python --上下文管理器實現

python --上下文管理器實現

 

深拷貝與淺拷貝 

淺拷貝:簡單的賦值拷貝操作,或者說編譯器自己生成的預設拷貝函式

深拷貝:在堆區重新申請空間,進行拷貝操作

 

class Person {
public:
    //無參(預設)建構函式
    Person() {
        cout << "無參建構函式!" << endl;
    }
    //有參建構函式
    Person(int age, int height) {

        cout << "有參建構函式!" << endl;

        m_age = age;
        //因為new是在堆區儲存資料,所以用一個指標接收返回資料
m_height = new int(height); } //解構函式 專門釋放堆區資料的 ~Person() { cout << "解構函式!" << endl; if (m_height != NULL) { //釋放在堆區中的資料。 delete m_height; //防止野指標出現,設定成空指標。 m_height = NULL; } } public:
int m_age; int* m_height; }; void test01() { Person p1(18, 180); cout << "p1的年齡: " << p1.m_age << " 身高: " << *p1.m_height << endl; Person p2(p1); cout << "p2的年齡: " << p2.m_age << " 身高: " << *p2.m_height << endl; }
int main() { test01(); system("pause"); return 0; }

 

當前程式碼執行起來之後會報錯:

 

 

因為在有參建構函式中建立了一個堆區的資料,在執行Person p2(p1)的時候編譯器預設的拷貝函式也會簡單的在棧上儲存height的地址,當離開test01這個函式體的時候自動呼叫解構函式,棧上的資料是先進後出(因為test01函式中沒有new,資料在棧上),所以先釋放p2的資料,這裡的解構函式是自己寫的,可以看到釋放了m_height在堆上的資料,當在釋放p1(注意p1上的m_height儲存的是堆地址,此時它是有值的,不會因為p2釋放了導致它在棧上的值沒有了)的時候又會重新釋放,根據棧上的地址找堆,發現找不到了,導致重複釋放報錯。

上述就是因為編譯器預設的淺拷貝造成的,如果屬性有在堆區開闢的,一定要自己提供拷貝建構函式,防止淺拷貝帶來的問題

自己建立拷貝函式解決:

class Person {
public:
    //無參(預設)建構函式
    Person() {
        cout << "無參建構函式!" << endl;
    }
    //有參建構函式
    Person(int age, int height) {

        cout << "有參建構函式!" << endl;

        m_age = age;
        //因為new是在堆區儲存資料,所以用一個指標接收返回資料
        m_height = new int(height);

    }
    //拷貝建構函式  
    Person(const Person& p) {
        cout << "拷貝建構函式!" << endl;
        //如果不利用深拷貝在堆區建立新記憶體,會導致淺拷貝帶來的重複釋放堆區問題
        m_age = p.m_age;
        //這樣不論呼叫多少次拷貝函式,前後的m_height中儲存的堆地址都不是一樣的了
        m_height = new int(*p.m_height);

    }

    //解構函式 專門釋放堆區資料的
    ~Person() {
        cout << "解構函式!" << endl;
        if (m_height != NULL)
        {
            //釋放在堆區中的資料。
            delete m_height;
            //防止野指標出現,設定成空指標。
            m_height = NULL;
        }
    }
public:
    int m_age;
    int* m_height;
};

void test01()
{
    Person p1(18, 180);

    cout << "p1的年齡: " << p1.m_age << " 身高: " << *p1.m_height << endl;

    Person p2(p1);
     
    cout << "p2的年齡: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}

int main() {

    test01();

    system("pause");

    return 0;
}

 

結果: