您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關C++內存管理如何理解,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
前言;
C++繼承了C語言的指針,一直以來指針的一些問題困擾著開發人員,常見的指針問題主要有:內存泄露、野指針、訪問越界等。值得慶幸的是C++標準委員會給我們提供了auto_ptr智能指針,后面又引入了share_ptr
以及weak_ptr
幫助我們正確和安全的使用指針,下面主要是介紹boost庫提供的解決方案。
在實際開發時,我們會根據不同的編程場景申請不同的資源,對于這些資源的管理需要一個完善的方案,我們希望在資源釋放后,C++能夠像java,c#一樣不用去手動的釋放資源而是由系統自動對資源進行回收。
C++編程時通常使用這種方法管理資源,申請的資源超過生命周期后,生命的對象自動調用析構函數對資源進行正確回收。如此看來,似乎是完美的解決我們的問題,至少在使用時不用手動釋放資源。但是這種資源釋放的方法同樣存在著缺陷,如果對象是在棧上創建得到,那么會自動調用析構函數,結果也是沒有問題的,但是如果對象是通過new在堆上創建的呢?結果是析構函數不能自動被調用,同樣需要我們使用delete進行顯示析構。如果程序在執行時沒有調用析構delete
進行釋放資源,那么同樣也會存在內存泄露的風險。
new/delete
在編程時一定要遵循配對原則,且要服從誰創建誰釋放的規則,這一點不管是新手程序員還是有著豐富編程經驗的老手都要認真對待。
從C98開始,C++標準委員會就給我們提供了智能指針:auto_ptr。它部分解決了資源的自動釋放問題。
使用方法如下:
std::auto_ptr<int> p (new int);
auto_ptr
的構造函數支持new操作符或者由對象工廠創建的對象指針作為參數。對象一經創建就托管了原始指針,因此它可以使用get方法返回指針對象,如:
*p.get() = 100;
auto_ptr
受到了大家的歡迎,越來越多的人使用這種技術解決了實際編程中大部分得到資源管理的問題,但是,auto_ptr
并不是一種非常完善的技術,也沒有覆蓋到智能指針的所有領域,尤其是引用計數型的智能指針。同理,在使用auto_ptr
的時候也要注意以下幾點,避免auto_ptr
的濫用。
auto_ptr不能共享所有權,即不要讓兩個auto_ptr指向同一個對象。
auto_ptr不能指向數組,因為auto_ptr
在析構的時候只是調用delete
。
auto_ptr只是一種簡單的智能指針,如有特殊需求,需要使用其他智能指針,比如share_ptr
。
auto_ptr不能作為容器對象。
為了解決auto_ptr
的不足,boost庫提供了多種類之中從而完善了auto_ptr的不足。這些指針都在boost庫的頭文件中,
如下所示:
#include <boost/smart_ptr.hpp> using namespace boost;
該類型指針和auto_ptr
類似,但是限制也更加嚴格,scoped_ptr
對象一旦獲取對象的管理權就將一直占用,不能在進行管理權轉移。scoped_ptr
像它的名字一樣,只能在起作用域內進行使用。使用后會使得代碼相對簡單且不會增加多余操作。
scoped_ptr使用方法:
scoped_ptr
使用簡單,只需要在原來使用new
的地方用scoped_ptr
進行替換即可,
使用方法如下:
scoped_ptr<string> pStr(new string("hello word"));
操作scoped_ptr指針也很簡單,使用方式和普通指針一致,如:
//打印指針指向字符串內容 cout<<pAtr<<endl; //打印字符長度 cout<<pAtr->size()<<endl;
需要注意的是:1)此指針對象會進行自動釋放,無需使用delete進行釋放,如果在實際編程時使用了delete,編譯器將會報錯,大家不妨可以思考下原因是什么歡迎留言。2)scoped_ptr
是不能進行賦值、拷貝操作得到,生命周期只限于聲明的作用域內。
和auto_ptr指針相比,scoped_ptr的不同點如下:
兩者都不能作為容器元素,但是原因卻不同。auto_ptr
是因為它自身的轉義語義,但是scoped_ptr
是因為不支持拷貝和復制。
指針所有權不同,auto_ptr
是可以進行轉義得到,但是scoped_ptr
不能進行轉義,因為其構造和拷貝函數都是私有的。
scoped_array
和scoped_ptr
基本相同,根本區別是scoped_array
是指向數組的,封裝了new[],彌補了指向數組的智能指針。
scoped_array使用方法:
scoped_array和scoped_ptr設計思想相同,使用方法也基本一致,如下:
scoped_array<int> pIntArray(new int[10]);
使用時需要注意的是:scoped_array
不會對數組范圍進行檢查,且不能通過數組名+偏移的方式進行獲取。
但可以按照以下方式使用:
pIntArray[0]=100; pIntArray[1]=200; 1.5 shared_ptr
shared_ptr
已經被引入C++標準庫中,功能強大,可以像普通指針那樣使用,它是引用計數型指針,可以被任意的復制和拷貝。同時shared_ptr
可以被用作容器元素。
可以說shared_ptr
是C++歷史上實現智能指針算法中最杰出的代表作。
shared_ptr使用方法:
shared_ptr指針是最接近原始指針的。他比auto_ptr
和scoped_ptr
應用范圍更廣,幾乎可以百分之百避免程序中的內存泄露,但是使用卻又像auto_ptr
和scoped_ptr一樣簡單。
shared_ptr
是線程安全的,可以由多個線程進行讀取。
使用方式如下:
int main() { //定義一個指針對象 shared_ptr<int> pInt(new int); //對指針進行賦值 *pInt = 100; cout<<*pInt<<endl; //調用shared_ptr重載方法 shared_ptr<int> pInt_cp = pInt; cout<<*pInt_cp<<endl; pInt.reset(); assert(!pInt); return 0; }
如上代碼所示shared_ptr
構造函數中依舊使用new的方法創建一個對象,但這個遠遠不夠,shared_ptr提供make_shared
方法來創建一個共享指針對象,
方式如下:
int main() { shared_ptr<string> pStr= make_shared<string>("hello world"); cout<<*pStr<<endl; shared_ptr<vector<int> > pVec = make_shared<vector<int> >(10,2); cout<<pVec->size()<<endl; return 0; }
代碼輸出結果為:
hello world
10
shared_ptr高級用法;
shared_ptr
可以保存任意類型指針,可以理解成是改指針是泛型的。
shared_ptr<void *>退出作用域后調用回調函數,如下:
void fun(void *p){} shared_ptr<void *> p((void *0),fun);
除此之外,shared_ptr
還有其它很多高級用法,如:延時釋放、包裝成員函數等,感興趣的話可以自行研究。
shared_array
功能和shared_ptr
類似,根本區別是包裝了new[]操作符,可以指向數組,知道引用計數為0時才會進行釋放。
shared_array使用方法:
shared_array
是shared_ptr
和scoped_array
的結合體。
使用方法如下所示:
int main() { int *p = new int[100]; shared_array<int> sp(p); shared_array<int> sp1=sp; sp[0]=10; return 0; }
weak_ptr
不具備普通指針的行為,需要和shared_ptr
配合使用。主要用于協助shared_ptr
工作,觀測資源的使用情況。
weak_ptr使用方法:
weak_ptr
和shared_ptr
共用可以通過shared_ptr
或者weak_ptr對象構造,使用時不會產生引用計數增加,析構時也不會導致引用計數的減少。可以使用use_count查看引用計數,也可以使用其等效的方法expired(),如果引用計數為0則表示觀測的對已經不存在了。代碼示例如下:
int main() { shared_ptr<int> p(new int(100)); cout<<p.use_count()<<endl; weak_ptr<int> wp(p); cout<<wp.use_count()<<endl; p.reset(); if(!wp.expired()) { shared_ptr<int> p1=wp.lock(); *p1 = 1000; cout<<wp.use_count()<<endl; } return 0; }
上述就是小編為大家分享的C++內存管理如何理解了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。