智能指针详解
原理
智能指針是一個類,用來存儲指向動態分配對象的指針,負責自動釋放動態分配的對象,防止堆內存泄漏。動態分配的資源,交給一個類對象去管理,當類對象聲明周期結束時,自動調用析構函數釋放資源
導引:
? ? ?智能指針最初只有auto_ptr,c++98版本的。但是auto_ptr存在一個致命問題是,它支持拷貝語義嘛。所以就會造成對一個指針delete兩次的問題,不安全。
? ? ?而解決對一個指針多次delete的問題,一共有三種解決思路
常用的智能指針
(1) shared_ptr
實現原理:采用引用計數器的方法,允許多個智能指針指向同一個對象,每當多一個指針指向該對象時,指向該對象的所有智能指針內部的引用計數加1,每當減少一個智能指針指向對象時,引用計數會減1,當計數為0的時候會自動的釋放動態分配的資源。
(2) unique_ptr
? ? ? ?unique_ptr采用的是獨享所有權語義,一個非空的unique_ptr總是擁有它所指向的資源。轉移一個unique_ptr將會把所有權全部從源指針轉移給目標指針,源指針被置空;所以unique_ptr不支持普通的拷貝和賦值操作,不能用在STL標準容器中;局部變量的返回值除外(因為編譯器知道要返回的對象將要被銷毀);如果你拷貝一個unique_ptr,那么拷貝結束后,這兩個unique_ptr都會指向相同的資源,造成在結束時對同一內存指針多次釋放而導致程序崩潰。
? ? ? ?在智能指針生命周期內,可以改變智能指針所指對象,如創建智能指針時通過構造函數指定、通過 reset 方法重新指定、通過 release 方法釋放所有權、通過移動語義轉移所有權,unique_ptr 還可能沒有對象,這種情況被稱為 empty。
? ? ? ?unique_ptr 可放在容器中,彌補了 auto_ptr 不能作為容器元素的缺點。只要對容器元素不使用拷貝操作的算法即可(如 sort())
? ? ? ?unique_ptr 比 auto_ptr 更加安全,因為 auto_ptr 有拷貝語義,拷貝后原對象變得無效,再次訪問原對象時會導致程序崩潰;unique_ptr 則禁止了拷貝語義,但提供了移動語義,即可以使用 std::move() 進行控制權限的轉移
(3) weak_ptr
? ? ? ?weak_ptr:弱引用。 引用計數有一個問題就是互相引用形成環(環形引用),這樣兩個指針指向的內存都無法釋放。需要使用weak_ptr打破環形引用。weak_ptr是一個弱引用,它是為了配合shared_ptr而引入的一種智能指針,它指向一個由shared_ptr管理的對象而不影響所指對象的生命周期,也就是說,它只引用,不計數。如果一塊內存被shared_ptr和weak_ptr同時引用,當所有shared_ptr析構了之后,不管還有沒有weak_ptr引用該內存,內存也會被釋放。所以weak_ptr不保證它指向的內存一定是有效的,在使用之前使用函數lock()檢查weak_ptr是否為空指針。
lock函數?檢查 weak_ptr 所指的對象是否仍存在,如果存在,返回一個指向共享對象的 shared_ptr,不存在則返回
w.lock(); //如果expired()為true,返回一個空shared_ptr,否則返回非空shared_ptr。
(4) auto_ptr
auto_ptr 是標準庫的較早版本包含的一個類,它具有 unique_ptr 的部分特性。相比于unique_ptr,不能在容器中保存 auto_ptr,也不能從函數返回 auto_ptr。盡量使用unique_ptr
主要是為了解決“有異常拋出時發生內存泄漏”的問題 。因為發生異常而無法正常釋放內存。
auto_ptr有拷貝語義,拷貝后源對象變得無效,這可能引發很嚴重的問題;而unique_ptr則無拷貝語義,但提供了移動語義,這樣的錯誤不再可能發生,因為很明顯必須使用std::move()進行轉移。
auto_ptr不支持拷貝和賦值操作,不能用在STL標準容器中。STL容器中的元素經常要支持拷貝、賦值操作,在這過程中auto_ptr會傳遞所有權,所以不能在STL中使用。
總結
- 上一篇: PDF的文件大小怎么压缩,两款高效的PD
- 下一篇: 沙箱测试