一個例子記住C++物件的生存週期
最近要考C++,複習過程中遇到一些問題,總結記錄一下。文中程式碼均在ideone線上編譯器中執行的。
程式碼
程式碼說明:
- 類A,含建構函式和解構函式
- 普通函式fun,函式體裡新建了類A的區域性自動物件
FunObj
和區域性靜態物件InStaObj
- main方法新建了類A的區域性自動物件
MainObj
,呼叫fun
方法 - 外面新建了A的的外部靜態物件
ExStaObj
和外部物件GblObj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <iostream> #include <string.h> using namespace std; class A { char string[50]; public : A(char * st); ~A( ); }; A::A(char * st) { strcpy(string, st); cout << string << "被建立時呼叫建構函式 ! " << endl; } A::~A( ) { cout << string << "被撤消時呼叫解構函式 ! " << endl; } void fun( ) { cout << "在fun( )函式體內 : \n" << endl; A FunObj("fun( )函式體內的自動物件FunObj"); static A InStaObj("內部靜態物件InStaObj"); } int main( ) { A MainObj("主函式體內的自動物件MainObj"); cout<<"主函式體內,呼叫fun()函式前: \n"; fun( ); cout << "\n主函式體內,呼叫fun()函式後:\n"; return 0; } static A ExStaObj("外部靜態物件ExStaObj"); A GblObj("外部物件GblObj"); |
輸出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
外部靜態物件ExStaObj被建立時呼叫建構函式 ! 外部物件GblObj被建立時呼叫建構函式 ! 主函式體內的自動物件MainObj被建立時呼叫建構函式 ! 主函式體內,呼叫fun()函式前: 在fun( )函式體內 : fun( )函式體內的自動物件FunObj被建立時呼叫建構函式 ! 內部靜態物件InStaObj被建立時呼叫建構函式 ! fun( )函式體內的自動物件FunObj被撤消時呼叫解構函式 ! 主函式體內,呼叫fun()函式後: 主函式體內的自動物件MainObj被撤消時呼叫解構函式 ! 內部靜態物件InStaObj被撤消時呼叫解構函式 ! 外部物件GblObj被撤消時呼叫解構函式 ! 外部靜態物件ExStaObj被撤消時呼叫解構函式 ! |
若將A GblObj("外部物件GblObj");
寫在static A ExStaObj("外部靜態物件ExStaObj");
前面,則輸出時兩者順序也顛倒。
分析
- 建立順序
外部靜態物件or外部物件優先於main函式 - 銷燬順序
和建立順序相反,注意靜態物件會在main函式執行完才會銷燬
記憶體的三種分配方式
- 從靜態儲存區分配:此時的記憶體在程式編譯的時候已經分配好,並且在程式的整個執行期間都存在。全域性變數,static變數等在此儲存
- 在棧區分配:相關程式碼執行時建立,執行結束時被自動釋放。區域性變數在此儲存。棧記憶體分配運算內建於處理器的指令集中,效率高,但容量有限
- 在堆區分配:動態分配記憶體。用new/malloc時開闢,delete/free時釋放。生存期由使用者指定,靈活。但有記憶體洩露等問題