jenkins +docker私有倉庫持續釋出+持續部署
阿新 • • 發佈:2022-03-25
深拷貝與淺拷貝
淺拷貝:簡單的賦值拷貝操作,或者說編譯器自己生成的預設拷貝函式
深拷貝:在堆區重新申請空間,進行拷貝操作
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; }
結果: