日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

《C++标准程序库》读书笔记(三)

發布時間:2025/6/15 c/c++ 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《C++标准程序库》读书笔记(三) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?????STL中的智能指針auto_ptr可以實現簡單的內存自動回收,防止內存泄漏(memory leakage)auto_ptr實際是一個類,在該類析構時自動調用delete,從而達到了內存回收的效果。但是,由于同一個指針同一時刻只能被一個auto_ptr占用,如果采用賦值操作(=)或者拷貝構造函數調用,就會發生所有權轉移,例如:

auto_ptr<int>?p(new?int(0));
auto_ptr
<int>?q;

此時,p擁有指向一個int的指針,q的指針為空。如果執行q=p;則,p指向空,q指向int;但是,這樣所有權轉換的問題同樣發生在參數傳遞中,例如

void?foo(auto_ptr<int>?t);

如果調用 foo(p);那么p就丟失了指針,所以一個解決方法是用引用例如:

void?foo1(auto_ptr<int>&?t);

void?foo2?(const?auto_ptr<int>&?t);

兩者都是可以的,不過foo1非常不安全,因為在函數里面很容易通過類似賦值的操作使t丟失指針,而foo2不會。例如

void?foo2(const?auto_ptr<int>&?t)
{?
?????auto_ptr
<int>?m;?m=t;
}

會發生編譯錯誤,從而避免災難的發生。但隨之又出現一個很大的問題,就是auto_ptr類的拷貝構造函數,或者賦值函數。最理想的情況是這樣(如果能成功,就不會有別的什么問題):

auto_ptr(const?auto_ptr&?rhs):ap(rhs.release()){}

但由于上述的原因,會發生編譯錯誤(因為調用了release(),release()會改變成員變量,不再是const)。所以只能去掉const,變為

auto_ptr(auto_ptr&?rhs):ap(rhs.release()){}

這樣可以編譯成功,而且往往也能正確運行,但是唯一的問題是: rhs為右值時會出現問題。

為了簡化問題,先假設拷貝構造函數什么都不做,即:

auto_ptr(auto_ptr& rhs){}

那么,如果有 auto_ptr<int> p(new int(10)),執行 auto_ptr<int> q(p),不會有任何問題,因為p是左值。但如果執行auto_ptr<int> q(auto_ptr<int>(new int(10))) ,則會發生編譯錯誤,因為auto_ptr<int>(new int(10)) 是右值,對右值的引用只能是常引用,也就是"const auto_ptr& rhs"的形式。但這里要注意的是,剛才那段代碼用VC編譯沒有任何問題,并且可以順利運行,但是用GCC之類的標準c++就不能順利編譯。

VCauto_ptr<int>& p=auto_ptr<int>(new int(0))? 是合法的,但在標準C++中是不合法的,只有const auto_ptr<int>& p=auto_ptr<int>(new int(0)) 才是合法的,也即在標準C++中,對右值的引用只能是常引用。所以說,要在標準C++中實現 auto_ptr<int> p(auto_ptr<int>(new int(0))) 就變得不可能了,因為如上所說,拷貝構造函數是這樣的形式:auto_ptr(auto_ptr<T>& rhs):ap(rhs.release()){}

但是不能把右值傳到一個非常引用中。但畢竟有聰明的人能想到解決辦法,利用代理類( proxy class)聲明如下結構,為了方便,我用int代替模板參

struct?auto_ptr_ref
{
???
int*?p;
???auto_ptr_ref(
int?*t):p(t){}
};

然后在auto_ptr類中增加了以下函數

auto_ptr(auto_ptr_ref?rhs):ap(rhs.p){}
auto_ptr
&?operator=(auto_ptr_ref?rhs){reset(rhs.p);?return?*this;}
operator?auto_ptr_ref(){return?auto_ptr_ref(release());}

之后,如果在標準C++有以下調用(VC中也會按照這個步驟調用,雖然沒有auto_ptr_ref它也能直接調用)

auto_ptr<int> p(auto_ptr<int>(new int(0)))

便可以成功,過程如下:

1. 構造臨時對象 auto_ptr<int>(new int(0))

2. 想將臨時對象通過拷貝構造函數傳給p,卻發現沒有合適的拷貝構造函數,因為只有auto_ptr(auto_ptr& rhs)這個不能用,又沒有auto_ptr(const auto_ptr& rhs) (因為用了在所有權轉移中會出錯)!

3. 編譯器只能曲線救國,看看類型轉換后能不能傳遞。

4. 由于我們定義了 operator auto_ptr_ref() 所以編譯器自然就可以試一下轉為 auto_ptr_ref類型。

5. 編譯器猛然間發現,我們定義了 auto_ptr(auto_ptr_ref rhs):ap(rhs.p){} 的構造函數,可以傳遞。

6. 順利構造p,任務完成。

其實說白了問題很簡單,因為構造函數不能接受右值,則取中間左值=右值, 然后再讓函數接受中間左值。 而這一系列過程正是利用編譯器能夠自動進行類型轉換而完成的。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的《C++标准程序库》读书笔记(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。