C++类和new、delete操作符和堆和栈内存的分配
生活随笔
收集整理的這篇文章主要介紹了
C++类和new、delete操作符和堆和栈内存的分配
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
如果你是Java、C#、PHP程序員,那么會對 new 非常熟悉,在這些編程語言中,只能通過 new 來創建對象。
在C++中,你可以像定義變量一樣來創建對象,如:
Student stu; //對象已被實例化,已分配內存空間,可以使用了 stu.say(); //調用成員函數
這種情況下,系統會在棧區為對象分配內存。棧區是內存中的一塊區域,由系統自動分配和釋放,程序員無法操控,一般用來存放函數的參數值、局部變量、局部對象等。
當發生函數調用時,系統將函數參數、局部變量、局部對象依次壓入棧區;函數執行結束,再按照先進后出的原則將它們彈出(銷毀)。
對于大部分程序,這不會有什么問題。但當你希望在函數調用結束前銷毀對象時,你是無能為力的?;蛘吣阆Mㄟ^ for 循環來創建多個對象,這種方法同樣也做不到。
這個時候 new 和 delete 就派上了用場:使用 new 創建的對象,可以在任意時刻通過 delete 銷毀,而且只需要一個指針指向它。
以前面的 Student 類為例,可以這樣來動態創建對象: new Student; 也可以使用構造函數: new Student("小明", 15, 90.5f); 這樣,就在堆區為對象分配了內存,并調用了構造函數。
但是此時程序員還無法訪問這個對象,因為這個對象既沒有名字,也沒有指針指向它。這種對象稱為 匿名對象 ,它確實存在,但無法訪問。
用一個指針來指向Student類的對象: Student *pStu; pStu = new Student("小明", 15, 90.5f); 或者: Student *pStu = new Student("小明", 15, 90.5f);
當不再需要對象時,可以通過 delete 銷毀: delete pStu; 這樣,就釋放掉了對象占用的內存,并調用了析構函數。
需要說明的是:new 在堆區為對象分配內存。與棧區不同的是,堆區內存由程序員分配和釋放,系統不會自動銷毀,即使函數調用結束了,仍然會保留堆區內存。如果程序員不主動回收堆區內存,那么只能在程序運行結束后由操作系統回收。
為了避免內存泄露,強烈建議 new 和 delete 成對出現,及時銷毀不再需要的對象。
例如,下面的代碼會造成嚴重的內存泄露:#include <iostream> #include <cstdlib> using namespace std; class Demo{ private: double n; double m; int i; }; void func(){ Demo *p = new Demo; } int main(){ int i; for(i=1; i<=1000000; i++){ func(); } system("pause"); return 0; }
當程序運行到?system("pause"); 語句時,你可以打開任務管理器,會發現這個小小的程序竟然占用了 32M 內存。
這是因為每次調用 func 函數,都會創建一個對象,并用 p 指向它。函數運行結束,僅僅釋放了指針變量 p 占用的內存,而沒有釋放 p 所指向的對象占用的內存。
如果在 func 函數中不回收對象內存,那么你將永遠無法回收,只能等到程序運行結束由操作系統回收,這就是典型的內存泄露。
另外注意,C語言中的 malloc、free 函數不能用來為對象分配和釋放內存。請看下面的例子:#include <iostream> using namespace std; class Demo{ public: Demo(); ~Demo(); }; Demo::Demo(){ cout<<"Constructor"<<endl; } Demo::~Demo(){ cout<<"Destructor"<<endl; } int main(){ cout<<"------new------"<<endl; Demo *p1 = new Demo; //創建一個對象 Demo *p2 = new Demo[5]; //創建一組對象 cout<<"------malloc------"<<endl<<endl; Demo *p3 = (Demo*)malloc(sizeof(Demo)); cout<<"------delete------"<<endl; delete p1; //銷毀一個對象 delete[] p2; //銷毀一組對象 cout<<"------free------"<<endl; free(p3); return 0; }
運行結果:
------new------
Constructor
Constructor
Constructor
Constructor
Constructor
Constructor
------malloc------
------delete------
Destructor
Destructor
Destructor
Destructor
Destructor
Destructor
------free------
從程序運行結果可以看出:malloc 雖然分配了內存,但沒有調用構造函數;free 雖然釋放了內存,但也沒有調用析構函數。
當發生函數調用時,系統將函數參數、局部變量、局部對象依次壓入棧區;函數執行結束,再按照先進后出的原則將它們彈出(銷毀)。
對于大部分程序,這不會有什么問題。但當你希望在函數調用結束前銷毀對象時,你是無能為力的?;蛘吣阆Mㄟ^ for 循環來創建多個對象,這種方法同樣也做不到。
這個時候 new 和 delete 就派上了用場:使用 new 創建的對象,可以在任意時刻通過 delete 銷毀,而且只需要一個指針指向它。
以前面的 Student 類為例,可以這樣來動態創建對象: new Student; 也可以使用構造函數: new Student("小明", 15, 90.5f); 這樣,就在堆區為對象分配了內存,并調用了構造函數。
但是此時程序員還無法訪問這個對象,因為這個對象既沒有名字,也沒有指針指向它。這種對象稱為 匿名對象 ,它確實存在,但無法訪問。
用一個指針來指向Student類的對象: Student *pStu; pStu = new Student("小明", 15, 90.5f); 或者: Student *pStu = new Student("小明", 15, 90.5f);
當不再需要對象時,可以通過 delete 銷毀: delete pStu; 這樣,就釋放掉了對象占用的內存,并調用了析構函數。
需要說明的是:new 在堆區為對象分配內存。與棧區不同的是,堆區內存由程序員分配和釋放,系統不會自動銷毀,即使函數調用結束了,仍然會保留堆區內存。如果程序員不主動回收堆區內存,那么只能在程序運行結束后由操作系統回收。
為了避免內存泄露,強烈建議 new 和 delete 成對出現,及時銷毀不再需要的對象。
例如,下面的代碼會造成嚴重的內存泄露:
這是因為每次調用 func 函數,都會創建一個對象,并用 p 指向它。函數運行結束,僅僅釋放了指針變量 p 占用的內存,而沒有釋放 p 所指向的對象占用的內存。
如果在 func 函數中不回收對象內存,那么你將永遠無法回收,只能等到程序運行結束由操作系統回收,這就是典型的內存泄露。
另外注意,C語言中的 malloc、free 函數不能用來為對象分配和釋放內存。請看下面的例子:
------new------
Constructor
Constructor
Constructor
Constructor
Constructor
Constructor
------malloc------
------delete------
Destructor
Destructor
Destructor
Destructor
Destructor
Destructor
------free------
從程序運行結果可以看出:malloc 雖然分配了內存,但沒有調用構造函數;free 雖然釋放了內存,但也沒有調用析構函數。
總結
以上是生活随笔為你收集整理的C++类和new、delete操作符和堆和栈内存的分配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu之find方法
- 下一篇: C++之char*,const char