亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++智能指針詳解

 更新時(shí)間:2022年08月17日 17:13:20   作者:頑張先生  
從比較簡單的層面來看,智能指針是RAII(Resource Acquisition Is Initialization,資源獲取即初始化)機(jī)制對普通指針進(jìn)行的一層封裝。這樣使得智能指針的行為動(dòng)作像一個(gè)指針,本質(zhì)上卻是一個(gè)對象,這樣可以方便管理一個(gè)對象的生命周期

優(yōu)缺點(diǎn):

  • 智能指針由原始指針的封裝,優(yōu)點(diǎn)是可以自動(dòng)分配內(nèi)存,不用擔(dān)心內(nèi)存泄漏問題。
  • 用于解決獨(dú)占/共享所有權(quán)指針的釋放,傳輸?shù)葐栴}。
  • 但是沒有原始指針方便。

一. unique_ptr獨(dú)占指針

特點(diǎn)

都是圍繞獨(dú)占展開

特點(diǎn)一: 如其名,獨(dú)占。也就是說同一個(gè)內(nèi)存空間同時(shí)只能有一個(gè)指針來管理。

int* pi = new int(10); //利用傳統(tǒng)指針在堆區(qū)開辟一個(gè)存放整數(shù)的區(qū)域
std::unique_ptr<int> u_pi_01{pi};//通過傳統(tǒng)指針創(chuàng)建智能指針
std::unique_ptr<int> u_pi_02{pi};//有意讓兩個(gè)獨(dú)占指針同時(shí)指向同一個(gè)內(nèi)存區(qū)域

這么寫編譯器不會(huì)報(bào)錯(cuò),但運(yùn)行時(shí)會(huì)提示 error:double free detected in tcache 2

這也就印證了第一個(gè)特點(diǎn),一個(gè)內(nèi)存區(qū)域只能由一個(gè)指針管理。

特點(diǎn)二: 當(dāng)指針超出作用域時(shí),內(nèi)存自動(dòng)釋放

//由于指針的本質(zhì)也是變量,離開作用范圍就會(huì)自動(dòng)釋放
//因此我們需要通過在外部創(chuàng)建變量來保存指針?biāo)4娴牡刂?
int* external_pi_1;//用于存儲(chǔ)傳統(tǒng)指針的地址
int* external_pi_2;//用于存儲(chǔ)智能指針的地址
 {
    int *pi = new int(10);//使用傳統(tǒng)指針在堆區(qū)開辟內(nèi)存存儲(chǔ)整形
    external_pi_1 = pi;   
    std::unique_ptr<int> u_pi{new int(10)};//使用智能指針在堆區(qū)開辟內(nèi)存存儲(chǔ)
    external_pi_2 = u_pi.get();
    std::cout << *external_pi_1 << std::endl;//輸出10
    std::cout << *external_pi_2 << std::endl;//輸出10
 }
std::cout << *external_pi_1 << std::endl;//輸出10
std::cout << *external_pi_2 << std::endl;//輸出0

可見傳統(tǒng)指針在局部作用域中開辟的內(nèi)存在外部同樣可以訪問,也就是說我們使用傳統(tǒng)指針開辟內(nèi)存之后在離開作用域時(shí)需要加上釋放內(nèi)存的操作,不然會(huì)造成內(nèi)存泄漏。

而智能指針我們不需要手動(dòng)釋放內(nèi)存,在離開作用域后會(huì)自動(dòng)釋放。

特點(diǎn)三:由于特點(diǎn)一,修改指針不可以copy ,只能Move(轉(zhuǎn)移歸屬權(quán))

std::unique_ptr<int> u_pi1 = std::make_unique<int>(10);
//std::unique_ptr<int> u_pi2 = u_pi1;//嘗試用拷貝的方式共享內(nèi)存,error:可別忘了這是獨(dú)占指針
std::unique_ptr<int> u_pi2 = move(u_pi1);使用move方法轉(zhuǎn)移內(nèi)存擁有權(quán)。

也就是說,通過move函數(shù),把指針u_pi1所指內(nèi)存中的值掏空,然后安到指針u_pi2所指的內(nèi)存上。

創(chuàng)建方式

方式一: 通過已有的傳統(tǒng)指針創(chuàng)建

int* pi = new int(10); //使用傳統(tǒng)指針在堆區(qū)開辟一個(gè)空間
std::unique_ptr<int> u_pi{pi};//利用創(chuàng)通指針創(chuàng)建智能指針

方式二: 通過new方法創(chuàng)建

std::unique_ptr<int> u_pi{new int(10)};

方式三: 通過std :: make_unique創(chuàng)建

std::unipue_ptr<int> u_pi = std::make_unique<int>(10);

傳遞方式

方式一: 通過move(),轉(zhuǎn)移擁有權(quán).

void show(std::unique_ptr<int> u_pi)
{
    std::cout<<*u_pi<<std::endl;
}
void test()
{
    std::unique_ptr<int> u_pi{new int(10)};
    show(move(u_pi)); //通過move轉(zhuǎn)移擁有權(quán)
}

注意:將指針的擁有權(quán)轉(zhuǎn)入函數(shù)中后,在原作用域指針將被釋放,而該指針將在函數(shù)調(diào)用結(jié)束時(shí)釋放。也就是說,將智能指針以move的形式傳入函數(shù)后,在原作用域不能再使用該指針。

方式二: 通過引用傳遞

void show(const std::unique_ptr<int> &u_pi)//加cosnt 不是不能改變指向的值,不能改變指針的指向
{
    std::cout << *u_pi << std::endl;
    //u_pi.reset();加了const所以不能清空
}
void test()
{
    std::unique_ptr<int> u_pi{new int(10)};
    show(u_pi);
}

注意: 將指針以引用的方式傳入函數(shù),那么該指針在原作用域依然存活,并可以和所調(diào)用函數(shù)共同操作該內(nèi)存空間數(shù)據(jù)。

方式三: 鏈?zhǔn)絺鬟f

std::unique_ptr<Person> get_unique(std::string str)
{
    std::unique_ptr<Person> u_pi{new Person(str)};
    return u_pi;
}
void test()
{
    get_unique("hua")->show();//鏈?zhǔn)?
}

簡單使用

  • 通過get()獲取地址
  • 可以通過->調(diào)用成員函數(shù)
  • 可以通過*調(diào)用解引用
  • 通過reset()清空指針
class Person
{
public:
    Perosn(std::string name):m_name(name){};
    void show()
    {
        std::cout<<"name is "<<m_name<<std::endl;
    }
private:
    std::string m_name;   
};
int main()
{
std::unique_ptr<Person> u_p{new Person("kimi")}; //用自定義類型創(chuàng)建
u_p->show();//可以通過->調(diào)用函數(shù)
(*u_p).show();//通過*解引用
std::cout<<u_p.get()<<std::endl;//通過get()獲取地址
u_p.reset();//清空指針
return 0;
}

隱藏危險(xiǎn)

用已有指針創(chuàng)建時(shí),沒有及時(shí)清空傳統(tǒng)指針,導(dǎo)致同時(shí)有兩個(gè)指針指向這塊已經(jīng)被“獨(dú)占”的區(qū)域。

int* pi = new int(10);
std::unique_ptr<int> u_pi{pi};//使用傳統(tǒng)指針創(chuàng)建,上式開辟的區(qū)域被獨(dú)占
*pi = 20; //沒有及時(shí)清空,依然可以通過獨(dú)占指針以外的方式修改內(nèi)存

二. shared_ptr 計(jì)數(shù)指針

特點(diǎn)

特點(diǎn)一: 可以通過copy共享內(nèi)存。

std::shared_ptr<int> u_pi_1{new int(10)};
std::shared_ptr<int> u_pi_2 = u_pi_1;//通過復(fù)制拷貝

特點(diǎn)二: 通過use_count();來查看計(jì)數(shù) ,copy 計(jì)數(shù)加一,銷毀計(jì)數(shù)減一。

std::shanred_ptr<int> s_pi{new int(10)}; //s_pi.use_count() == 1
std::shanred_ptr<int> s_pi_copy = s_pi;  //s_pi.use_count() == 2
s_pi = nullptr;//清空指針                 //s_pi_copy.use_count() == 1

特點(diǎn)三: 無論多少指針,都同用一份數(shù)據(jù),因而同一份數(shù)據(jù)的use_count()一致。

std::shared_ptr<int> s_pi{new int(10)}; //s_pi.use_count() == 1
std::shared_ptr<int> s_pi_2 = s_pi;     //s_pi.use_count() == 2
std::shared_ptr<int> s_pi_3 = s_pi_2;   //s_pi.use_count() == 3
s_pi_2 = bullptr; //清空2指針            //s_pi.use_count() == 2

傳遞方式

  • 本質(zhì)不變,在函數(shù)調(diào)用中,因?yàn)楸旧碇С謴?fù)制操作,所以不用加move可以直接傳遞。
  • 并且在傳遞到函數(shù)中,use_count() 會(huì)增加,并在函數(shù)銷毀時(shí)候還原。
  • 在函數(shù)中修改指向的值,在外部的指針指向的值也會(huì)改變。
  • 使用引用傳遞,則在傳遞到函數(shù)中時(shí),計(jì)數(shù)不會(huì)增加。
void get_use_1(std::shared_ptr<int> s_pi)
{
    std::cout << s_pi.use_count() << std::endl;
}
void get_use_2(std::shared_ptr<int>& s_pi)
{
    std::cout << s_pi.use_count() << std::endl;
}
void test()
{
    std::shared_ptr<int> s_pi{new int(10)};
    std::cout << s_pi.use_count() << std::endl;
    get_use_1(s_pi);//在函數(shù)中計(jì)數(shù)會(huì)增加,但隨著函數(shù)銷毀,計(jì)數(shù)復(fù)原
    get_use_2(s_pi);//以引用方式傳入,指針還是那個(gè)指針,計(jì)數(shù)不會(huì)增加
}

輸出:1 2 1

隱藏危險(xiǎn)

share_ptr帶來的循環(huán)依賴問題

class Person
{
public:
    void set_friend(share_ptr<Person> p)
 
    _friend = p;
private:
    share_ptr<Person> _frient;
};
int main()
{
   share_ptr<Person> p1 = make_shared("P1");
   share_ptr<Person> p2 = make_shared("P2");
    p1->set_friend(P2);
    p2->set_friend(P1);//造成循環(huán)依賴,在main中的話,不會(huì)執(zhí)行析構(gòu)
}

解決:將_friend屬性改為weak_ptr 。

三. weak_ptr

weak_ptr 是一個(gè)不需要所有權(quán)的指針,所以我們可以通過用weak_ptr來聲明屬性,解決循環(huán)依賴

class Person
{
public:
    void set_friend(share_ptr<Person> p)
    _friend = p;
private:
    weak_ptr<Person> _frient;//使用weak_ptr解決循環(huán)依賴
};
int main()
{
    share_ptr<Person> p1 = make_shared("P1");
    share_ptr<Person> p2 = make_shared("P2");
    p1->set_friend(P2);
    p2->set_friend(P1);
}

可以通過lock()來將weak_pte升級為shared_ptr;

std::weak_ptr<Person> w_pi{new Person("hua")};
std::shared_ptr <Person> s_pi2 = w_pi.lock();

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

相關(guān)文章

  • 一文詳解Qt的QObject類

    一文詳解Qt的QObject類

    Qt的QObject類是Qt框架中的基類,它是所有Qt對象的父類,本文主要介紹了Qt的QObject類,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • 詳解C++編程中的vector類容器用法

    詳解C++編程中的vector類容器用法

    vector是一個(gè)標(biāo)準(zhǔn)庫中的容器,使用時(shí)需要包含#include <vector>頭文件,也可以說vector是一個(gè)類模板而不是一種數(shù)據(jù)類型,對它的定義,需要指定類型,需要的朋友可以參考下
    2016-05-05
  • 在C++中加載TorchScript模型的方法

    在C++中加載TorchScript模型的方法

    這篇文章主要介紹了在C++中加載TorchScript模型的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • wxWidgets實(shí)現(xiàn)無標(biāo)題欄窗口拖動(dòng)效果

    wxWidgets實(shí)現(xiàn)無標(biāo)題欄窗口拖動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了wxWidgets實(shí)現(xiàn)無標(biāo)題欄窗口拖動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • 一文帶你了解C++中deque的使用

    一文帶你了解C++中deque的使用

    C++中的deque是一種雙端隊(duì)列,可以在隊(duì)列的前端和后端進(jìn)行插入元素和刪除操作,同時(shí)可以視作一個(gè)長度不定的數(shù)組,支持高效的插入和刪除操作。本篇文章將深入探討C++中的deque的使用,感興趣的可以了解一下
    2023-05-05
  • c語言中聯(lián)合體和枚舉用法詳解

    c語言中聯(lián)合體和枚舉用法詳解

    結(jié)構(gòu)體、聯(lián)合體是C語言中的構(gòu)造類型,結(jié)構(gòu)體我們平時(shí)應(yīng)該都用得很多,下面這篇文章主要給大家介紹了關(guān)于c語言中聯(lián)合體和枚舉用法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • C語言 指針與二維數(shù)組詳解

    C語言 指針與二維數(shù)組詳解

    本文主要介紹C語言 指針與二維數(shù)組,這里整理了詳細(xì)的資料及示例代碼,有需要的小伙伴可以參考下
    2016-08-08
  • C語言的指針類型詳細(xì)解析

    C語言的指針類型詳細(xì)解析

    C語言的指針類型包括兩方面的信息:一是地址,存放在指針變量中;二是類型信息,關(guān)乎于讀寫的長度,沒有存儲(chǔ)在指針變量中,位于用該指針讀寫時(shí)的mov指令中,不同的讀寫長度對應(yīng)的mov指令不同
    2013-09-09
  • MFC自繪Button按鈕分析和實(shí)現(xiàn)

    MFC自繪Button按鈕分析和實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了MFC自繪Button按鈕分析和實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C/C++ 中實(shí)現(xiàn)讓控制臺(tái)暫停的方法

    C/C++ 中實(shí)現(xiàn)讓控制臺(tái)暫停的方法

    這篇文章主要介紹了C/C++ 中實(shí)現(xiàn)讓控制臺(tái)暫停的方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07

最新評論