最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++各種智能指針的使用小結(jié)

 更新時(shí)間:2026年07月16日 09:02:35   作者:華麗的周遭  
本文主要介紹了C++各種智能指針的使用小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

C++智能指針是RAII(資源獲取即初始化)思想的核心實(shí)踐,用于自動(dòng)管理動(dòng)態(tài)內(nèi)存,解決傳統(tǒng)裸指針的內(nèi)存泄漏、懸垂指針重復(fù)釋放等問(wèn)題。

C++11及后續(xù)標(biāo)準(zhǔn)提供了多種智能指針,核心區(qū)別在于所有權(quán)模型(獨(dú)占/共享/弱引用),定義在<memory> 頭文件中。

一、智能指針的分類與核心特性

C++標(biāo)準(zhǔn)庫(kù)中的智能指針主要有4種(auto_ptr已被廢棄):

類型

所有權(quán)模型

核心特點(diǎn)

auto_ptr

獨(dú)占(已廢棄)

拷貝時(shí)轉(zhuǎn)移所有權(quán),易導(dǎo)致意外失效,禁止使用?

unique_ptr

獨(dú)占所有權(quán)

同一時(shí)間僅一個(gè)指針擁有對(duì)象,不可拷貝,僅可移動(dòng)?

shared_ptr

共享所有權(quán)

多個(gè)指針共享對(duì)象,通過(guò)引用計(jì)數(shù)跟蹤所有者數(shù)量,計(jì)數(shù)歸零時(shí)釋放對(duì)象

weak_ptr

弱引用(無(wú)所有權(quán))

指向shared_ptr管理的對(duì)象,但不增加引用計(jì)數(shù),用于解決循環(huán)引用

二、各智能指針詳解

1.unique_ptr:獨(dú)占所有權(quán)的輕量級(jí)指針

unique_ptr最常用的智能指針之一,適用于單一所有者的場(chǎng)景(如動(dòng)態(tài)數(shù)組、局部資源管理)。

核心特性:

  • 獨(dú)占性:不能拷貝(copy constructor/copy assignment被刪除),只能通過(guò)std::move轉(zhuǎn)移所有權(quán)。
  • 輕量:大小與裸指針相同(無(wú)額外開(kāi)銷,除非自定義刪除器)。
  • 支持?jǐn)?shù)組unique_ptr<T[]>重載了operator[],自動(dòng)用delete[]釋放。
  • 自定義刪除器:可指定任意資源釋放邏輯(如文件句柄、網(wǎng)絡(luò)連接)。

用法示例:

#include <memory>
#include <iostream>

int main() {
    // 1. 創(chuàng)建:優(yōu)先用make_unique(C++14引入,更安全高效)
    std::unique_ptr<int> p1 = std::make_unique<int>(42); 
    // 等價(jià)于:std::unique_ptr<int> p1(new int(42));

    // 2. 訪問(wèn)對(duì)象:用*或->
    std::cout << *p1 << std::endl; // 輸出42

    // 3. 移動(dòng)所有權(quán)(不可拷貝)
    std::unique_ptr<int> p2 = std::move(p1); // p1失去所有權(quán),變?yōu)閚ullptr
    if (!p1) std::cout << "p1 is null" << std::endl;

    // 4. 數(shù)組版本
    std::unique_ptr<int[]> arr = std::make_unique<int[]>(3);
    arr[0] = 1; arr[1] = 2; arr[2] = 3;

    // 5. 釋放所有權(quán):release()返回裸指針,不再管理
    int* raw = p2.release();
    delete raw; // 需手動(dòng)釋放(不推薦,盡量用智能指針全程管理)

    // 6. 重置:reset()釋放當(dāng)前對(duì)象,可選新對(duì)象
    p2.reset(new int(100)); // 先釋放原對(duì)象(若有),再管理新對(duì)象
    p2.reset(); // 釋放對(duì)象,變?yōu)閚ullptr

    return 0;
}

自定義刪除器示例(管理文件句柄):

#include <cstdio>
#include <memory>

// 自定義刪除器:關(guān)閉文件
struct FileDeleter {
    void operator()(FILE* fp) const {
        if (fp) std::fclose(fp);
    }
};

int main() {
    // 用自定義刪除器創(chuàng)建unique_ptr
    std::unique_ptr<FILE, FileDeleter> fp(std::fopen("test.txt", "w"));
    if (fp) std::fputs("hello", fp.get()); // get()返回裸指針
    // 離開(kāi)作用域時(shí),自動(dòng)調(diào)用FileDeleter釋放文件
    return 0;
}

2.shared_ptr:共享所有權(quán)的引用計(jì)數(shù)指針

shared_ptr適用于多所有者的場(chǎng)景(如容器中存儲(chǔ)動(dòng)態(tài)對(duì)象、跨模塊共享資源)。

核心特性:

  • 共享性:多個(gè)shared_ptr可指向同一對(duì)象,通過(guò)引用計(jì)數(shù)跟蹤所有者數(shù)量。
  • 引用計(jì)數(shù):每次拷貝shared_ptr,計(jì)數(shù)+1;析構(gòu)或reset()時(shí),計(jì)數(shù)-1;計(jì)數(shù)歸零時(shí),釋放對(duì)象。
  • 高效創(chuàng)建:優(yōu)先用std::make_shared(C++11引入),一次性分配對(duì)象內(nèi)存控制塊(含引用計(jì)數(shù)、弱引用計(jì)數(shù)),比直接new更高效。
  • 線程安全:引用計(jì)數(shù)的增減是原子操作(多線程安全),但對(duì)象本身的訪問(wèn)需額外同步(如互斥鎖)。

用法示例:

#include <memory>
#include <iostream>

int main() {
    // 1. 創(chuàng)建:優(yōu)先用make_shared(更高效)
    auto p1 = std::make_shared<int>(42); 
    std::cout << "use_count: " << p1.use_count() << std::endl; // 輸出1

    // 2. 共享所有權(quán):拷貝時(shí)計(jì)數(shù)+1
    auto p2 = p1; 
    std::cout << "use_count: " << p1.use_count() << std::endl; // 輸出2

    // 3. 釋放所有權(quán):reset()減少計(jì)數(shù)
    p1.reset(); 
    std::cout << "use_count after p1.reset(): " << p2.use_count() << std::endl; // 輸出1

    // 4. 自定義刪除器(管理動(dòng)態(tài)數(shù)組)
    auto arr = std::shared_ptr<int>(new int[3], [](int* p) { delete[] p; });
    arr.get()[0] = 1; // 訪問(wèn)數(shù)組元素

    return 0;
}

注意:make_sharedVS 直接new

make_shared的優(yōu)勢(shì):

  • 更安全:避免裸指針暴露(如func(std::shared_ptr<int>(new int), func2())可能因編譯器優(yōu)化導(dǎo)致內(nèi)存泄漏);
  • 更高效:一次性分配對(duì)象和控制塊,減少內(nèi)存碎片;
  • 異常安全:構(gòu)造過(guò)程中若拋出異常,make_shared不會(huì)泄漏內(nèi)存。

例外情況:需要自定義刪除器延遲初始化時(shí),只能用new。

3.weak_ptr:弱引用指針(解決循環(huán)引用)

weak_ptrshared_ptr的“觀察者”,不擁有對(duì)象所有權(quán),僅指向shared_ptr管理的對(duì)象,用于解決循環(huán)引用問(wèn)題。

核心問(wèn)題:循環(huán)引用

當(dāng)兩個(gè)shared_ptr互相指向?qū)Ψ綍r(shí),引用計(jì)數(shù)永遠(yuǎn)無(wú)法歸零,導(dǎo)致內(nèi)存泄漏

#include <memory>

struct A { std::shared_ptr<B> b; };
struct B { std::shared_ptr<A> a; };

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();
    a->b = b; // A的b指向B,B的計(jì)數(shù)+1(變?yōu)?)
    b->a = a; // B的a指向A,A的計(jì)數(shù)+1(變?yōu)?)
    // 離開(kāi)作用域時(shí),a和b的計(jì)數(shù)各減1(變?yōu)?),無(wú)法釋放!
    return 0;
}

weak_ptr的解決方案

將其中一個(gè)shared_ptr改為weak_ptr(弱引用,不增加計(jì)數(shù)):

struct A { std::weak_ptr<B> b; }; // 弱引用,不增加B的計(jì)數(shù)
struct B { std::weak_ptr<A> a; }; // 弱引用,不增加A的計(jì)數(shù)

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();
    a->b = b; // B的計(jì)數(shù)仍為1(weak_ptr不增加)
    b->a = a; // A的計(jì)數(shù)仍為1(weak_ptr不增加)
    // 離開(kāi)作用域時(shí),a和b的計(jì)數(shù)各減1(變?yōu)?),正常釋放!
    return 0;
}

weak_ptr的用法:

  • 創(chuàng)建:由shared_ptr構(gòu)造,或通過(guò)lock()獲取shared_ptr。
  • 訪問(wèn)對(duì)象:必須用lock()轉(zhuǎn)換為shared_ptr(若對(duì)象已釋放,返回空shared_ptr)。
  • 檢查有效性:用expired()判斷對(duì)象是否已釋放(use_count() == 0)。

示例:

#include <memory>
#include <iostream>

int main() {
    auto sp = std::make_shared<int>(42);
    std::weak_ptr<int> wp = sp; // 弱引用指向sp的對(duì)象

    // 1. 檢查有效性
    if (!wp.expired()) {
        std::cout << "Object exists" << std::endl;
    }

    // 2. 訪問(wèn)對(duì)象:lock()獲取shared_ptr
    auto locked_sp = wp.lock();
    if (locked_sp) {
        std::cout << *locked_sp << std::endl; // 輸出42
    }

    // 3. 釋放原對(duì)象
    sp.reset();
    if (wp.expired()) {
        std::cout << "Object has been released" << std::endl;
    }

    return 0;
}

三、智能指針的關(guān)鍵注意事項(xiàng)

  • 禁止用裸指針初始化多個(gè)智能指針
    • 會(huì)導(dǎo)致多個(gè)智能指針獨(dú)立管理同一對(duì)象,析構(gòu)時(shí)重復(fù)釋放。
    • ? 錯(cuò)誤:int* p = new int; auto p1 = std::shared_ptr<int>(p); auto p2 = std::shared_ptr<int>(p);
    • ? 正確:auto p1 = std::make_shared<int>(42); auto p2 = p1;
  • 優(yōu)先用make_shared/make_unique:
    • 避免裸指針暴露,提升安全性和效率(見(jiàn)前文)。
  • 避免循環(huán)引用
    • weak_ptr打破shared_ptr之間的雙向依賴(見(jiàn)前文)。
  • 不要手動(dòng)delete智能指針的get()結(jié)果:
    • get()返回的裸指針是智能指針內(nèi)部管理的,手動(dòng)delete會(huì)導(dǎo)致雙重釋放。
  • 線程安全
    • shared_ptr引用計(jì)數(shù)是線程安全的(原子操作);
    • shared_ptr對(duì)象本身不是線程安全的(多線程訪問(wèn)需同步);
    • unique_ptr不支持多線程(獨(dú)占性)。

四、智能指針的選擇指南

場(chǎng)景

推薦智能指針

單一所有者(如局部變量)

unique_ptr

多所有者(如容器共享)

shared_ptr

解決循環(huán)引用

weak_ptr

管理數(shù)組

unique_ptr<T[]>

管理非內(nèi)存資源(文件、socket)

帶自定義刪除器的unique_ptr/shared_ptr

五、總結(jié)

智能指針是C++現(xiàn)代編程的必備工具,核心是通過(guò)所有權(quán)模型自動(dòng)管理內(nèi)存。記?。?/p>

  • 獨(dú)占用unique_ptr,共享用shared_ptr
  • 循環(huán)引用用weak_ptr破局;
  • 優(yōu)先用make_shared/make_unique;
  • 避免裸指針與智能指針混用。

掌握智能指針能大幅減少內(nèi)存錯(cuò)誤,提升代碼的健壯性和可維護(hù)性——這也是嵌入式Linux開(kāi)發(fā)中(如驅(qū)動(dòng)、Qt應(yīng)用、流媒體資源管理)的關(guān)鍵技能。

到此這篇關(guān)于C++各種智能指針的使用小結(jié)的文章就介紹到這了,更多相關(guān)C++各種智能指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c語(yǔ)言實(shí)現(xiàn)把文件中數(shù)據(jù)讀取并存到數(shù)組中

    c語(yǔ)言實(shí)現(xiàn)把文件中數(shù)據(jù)讀取并存到數(shù)組中

    下面小編就為大家?guī)?lái)一篇c語(yǔ)言實(shí)現(xiàn)把文件中數(shù)據(jù)讀取并存到數(shù)組中。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • C++17中的std::from_chars函數(shù)使用及說(shuō)明

    C++17中的std::from_chars函數(shù)使用及說(shuō)明

    這篇文章主要介紹了C++17中的std::from_chars函數(shù)使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-10-10
  • C++實(shí)現(xiàn)職工工資管理系統(tǒng)

    C++實(shí)現(xiàn)職工工資管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單的職工工資管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 基于C/C++時(shí)間函數(shù)的使用詳解

    基于C/C++時(shí)間函數(shù)的使用詳解

    本篇文章是對(duì)C/C++時(shí)間函數(shù)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 淺談使用Rapidxml 庫(kù)遇到的問(wèn)題和分析過(guò)程(分享)

    淺談使用Rapidxml 庫(kù)遇到的問(wèn)題和分析過(guò)程(分享)

    下面小編就為大家?guī)?lái)一篇淺談使用Rapidxml 庫(kù)遇到的問(wèn)題和分析過(guò)程(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • VS2019配置BOOST的方法(v1.70.0庫(kù))

    VS2019配置BOOST的方法(v1.70.0庫(kù))

    這篇文章主要介紹了VS2019配置BOOST的方法(v1.70.0庫(kù)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • C++異常機(jī)制:棧展開(kāi)、異常傳播與異常安全

    C++異常機(jī)制:棧展開(kāi)、異常傳播與異常安全

    本文主要介紹了C語(yǔ)言和C++處理錯(cuò)誤的方式,C語(yǔ)言提供了終止程序、返回錯(cuò)誤碼、errno等方式,而C++引入了異常處理機(jī)制,通過(guò)throw拋出異常,通過(guò)try-catch捕獲和處理異常,異常處理可以提高程序的健壯性
    2026-05-05
  • C語(yǔ)言編程中實(shí)現(xiàn)二分查找的簡(jiǎn)單入門(mén)實(shí)例

    C語(yǔ)言編程中實(shí)現(xiàn)二分查找的簡(jiǎn)單入門(mén)實(shí)例

    這篇文章主要介紹了C語(yǔ)言編程中實(shí)現(xiàn)二分查找的簡(jiǎn)單入門(mén)實(shí)例,需要的朋友可以參考下
    2015-12-12
  • C++高精度算法的使用場(chǎng)景詳解

    C++高精度算法的使用場(chǎng)景詳解

    在我們進(jìn)行計(jì)算的過(guò)程中,經(jīng)常會(huì)遇到幾十位,甚至幾百位的數(shù)字的計(jì)算問(wèn)題,也有可能會(huì)遇到小數(shù)點(diǎn)后幾十位,幾百位的情況,而我們面對(duì)這樣的情況下,long long  和 double 的數(shù)據(jù)范圍顯然是不夠使用的了。因此這時(shí),我們就需要引入一個(gè)新的算法,叫做高精度算法
    2022-09-09
  • C++超詳細(xì)講解字符串類

    C++超詳細(xì)講解字符串類

    在C++中只有一個(gè)字符串類,即basic_string,其管理著一個(gè) '\0' 結(jié)尾的字符數(shù)組。頭文件:#include <string>,string類支持兩種輸入方式:cin方式和getline()方式
    2022-06-06

最新評(píng)論

新蔡县| 万载县| 于都县| 瓮安县| 保德县| 宁乡县| 厦门市| 海晏县| 靖远县| 淮北市| 香格里拉县| 桦甸市| 宁德市| 本溪市| 乌兰县| 郁南县| 临泽县| 宽城| 宝丰县| 客服| 清流县| 锡林郭勒盟| 沅江市| 班玛县| 信阳市| 封开县| 武清区| 乌鲁木齐县| 平原县| 磐石市| 东城区| 驻马店市| 闽侯县| 平原县| 阜康市| 天水市| 鹿邑县| 黔东| 新建县| 盈江县| 兴化市|