欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++深入分析講解智能指針

 更新時(shí)間:2022年05月11日 11:44:10   作者:GG_Bond18  
為了解決內(nèi)存泄漏的問題,C++中提出了智能指針。內(nèi)存泄漏的產(chǎn)生原因有很多,即使我們正確的使用malloc和free關(guān)鍵字也有可能產(chǎn)生內(nèi)存泄漏,如在malloc和free之間如果存在拋異常,那也會(huì)產(chǎn)生內(nèi)存泄漏。這種問題被稱為異常安全

1.簡介

程序運(yùn)行時(shí)存在靜態(tài)空間、棧和堆區(qū),用堆來存儲(chǔ)動(dòng)態(tài)分配空間的對(duì)象即那些在程序運(yùn)行時(shí)分配空間的對(duì)象,若該對(duì)象不再使用,我們必須顯式的銷毀它們,避免內(nèi)存泄漏。

智能指針是一個(gè)可以像指針一樣工作的對(duì)象,有unique_ptr(獨(dú)占指針),shared_ptr與weak_ptr等智能指針,定義在<memory>頭文件中,可以對(duì)動(dòng)態(tài)資源進(jìn)行管理。

保證以構(gòu)造的對(duì)象最終會(huì)銷毀,即它的析構(gòu)函數(shù)最終會(huì)被調(diào)用。

注意:

1.為了避免內(nèi)存泄漏,通過智能指針管理的對(duì)象應(yīng)該沒有其他的引用指向它們.

2.智能指針不支持指針的算術(shù)運(yùn)算

2.unique_ptr指針(獨(dú)占指針)

我們大多數(shù)場景下用到的都是unique_ptr。

其在默認(rèn)情況下和普通指針的大小是相同,內(nèi)存上沒有任何的額外消耗,性能最優(yōu)。

注意:

1.不能使用其他unique_ptr對(duì)象的值來初始化一個(gè)unique_ptr。也不能將一個(gè)unique_ptr對(duì)象賦值給另外一個(gè)。這樣的操作將導(dǎo)致兩個(gè)獨(dú)占指針共享相同對(duì)象的所有權(quán)。

2.unique_ptr代表的是專屬所有權(quán),如果想要把一個(gè)unique_ptr的內(nèi)存交給另外一個(gè)unique_ptr對(duì)象管理。

只能使用std::move轉(zhuǎn)移當(dāng)前對(duì)象的所有權(quán)。轉(zhuǎn)移之后,當(dāng)前對(duì)象不再持有此內(nèi)存,新的對(duì)象將獲得專屬所有權(quán)。

3.若unique_ptr指向的是一個(gè)對(duì)象數(shù)組的話,要確保調(diào)用delete[]來處理被解除分配的數(shù)組,則應(yīng)該在對(duì)象類型后面包含一對(duì)空的方括號(hào)[]。

#include<iostream>
#include<memory>
using namespace std;
int main() 
{
    unique_ptr<int> up1(new int(11));
    cout << "up = " << *up1 << endl;
    //將up1的獨(dú)占權(quán)轉(zhuǎn)移給up2,up1不能再操作堆區(qū)空間
    unique_ptr<int> up2 = std::move(up1);
    cout << "up2 = " << *up2 << endl;
    //up2.reset();//若為無參作用是顯示釋放堆區(qū)內(nèi)容
    up2.reset(new int(22));//若為有參,先釋放原來堆區(qū)內(nèi)容,重新給up2綁定一個(gè)新的堆區(qū)內(nèi)容
    cout << "up2 = " << *up2 << endl;
    //釋放控制權(quán),但不釋放堆區(qū)內(nèi)存
    int* p = up2.release();
    cout <<"p = "<< *p << endl;
    delete p;
    p = nullptr;
    return 0;
}
#include<iostream>
#include<memory>
using namespace std;
int main()
{
    //指向數(shù)組的獨(dú)占指針
    unique_ptr<int[] > up(new int[5]);
    for (int k = 0; k < 5; k++)
    {
        up[k] = k+1;
    }
    for (int k = 0; k < 5; k++)
    {
        cout << up[k] << " ";
    }
    cout << endl;
    return 0;
}

3.shared_ptr指針(共享所有權(quán))

多個(gè)shared_ptr智能指針可以共同使用同一塊堆內(nèi)存。由于該類型智能指針在實(shí)現(xiàn)上采用的是引用計(jì)數(shù)機(jī)制,

即便有一個(gè)shared_ptr指針放棄了堆內(nèi)存的"使用權(quán)"(引用計(jì)數(shù)減1)也不會(huì)影響其他指向同一堆內(nèi)存的shared_ptr指針(只有引用計(jì)數(shù)為0時(shí),堆內(nèi)存才會(huì)被自動(dòng)釋放)

#include<iostream>
#include<memory>
using namespace std;
int main()
{
    shared_ptr<int> sp1(new int(11));
    shared_ptr<int>sp2(sp1);//拷貝構(gòu)造
    cout << "num = " << sp2.use_count() << endl;//打印計(jì)數(shù)器 2
    sp1.reset();
    cout << "num = " << sp2.use_count() << endl;//1
    cout << *sp2 << endl;//11
    sp1.reset();
    cout << "num = " << sp1.use_count() << endl;//0
    return 0;
}

shared_ptr的內(nèi)存占用是裸指針的兩倍。因?yàn)槌艘芾硪粋€(gè)裸指針外,還要維護(hù)一個(gè)引用計(jì)數(shù)。 因此相比于unique_ptr, shared_ptr的內(nèi)存占用更高。

4.weak_ptr(輔助作用)

該類型指針通常不單獨(dú)使用(沒有實(shí)際用處),只能和shared_ptr搭配使用。我們可以將weak_ptr視為shared_ptr指針的一種輔助工具。

借助weak_ptr類型指針,我們可以獲取shared_ptr指針的一些狀態(tài)信息,比如有多少指向相同的shared_ptr指針,shared_ptr指針指向的堆內(nèi)存是否已經(jīng)被釋放等。

當(dāng)weak_ptr類型指針的指向和某一shared_ptr指針相同時(shí),weak_ptr并不會(huì)使所指堆內(nèi)存的引用計(jì)數(shù)加1

當(dāng)weak_ptr指針被釋放時(shí),之前所指堆內(nèi)存的引用計(jì)數(shù)也不會(huì)因此而減1.也就是說,weak_ptr并不會(huì)影響所指堆內(nèi)存空間的引用計(jì)數(shù)。

weak_ptr<T>模板類中沒有重載*和->運(yùn)算符 , weak_ptr 類型指針只能訪問所指的堆內(nèi)存,而無法修改它

#include<iostream>
#include<memory>
using namespace std;
int main()
{
    shared_ptr<int>sp1(new int(11));
    shared_ptr<int>sp2(sp1);
    weak_ptr<int>wp = sp1;
    cout << wp.use_count() << endl;
    shared_ptr<int>sp3 = wp.lock();
    //lock() 若當(dāng)前weak_ptr已經(jīng)過期,則該函數(shù)會(huì)返回一個(gè)空的shared_ptr指針.反之,該函數(shù)返回一個(gè)和當(dāng)前weak_ptr指向相同的shared_ptr。
    cout << wp.use_count() << endl;
    if (sp3 == nullptr)
    {
        cout << "堆區(qū)空間已經(jīng)釋放" << endl;
    }
    else
    {
        //cout << *wp << endl;//err
        cout << *sp3 << endl;//間接訪問
    }
    return 0;
}

5.自實(shí)現(xiàn)初級(jí)版智能指針

#include<iostream>
using namespace std;
class Person
{
public:
    Person(int age)
    {
        cout << "有參構(gòu)造函數(shù)調(diào)用" << endl;
        m_age = age;
    }
    void showage()
    {
        cout << "年齡為:" << this->m_age << endl;
    }
    ~Person()
    {}
    int m_age;
};
//利用智能指針管理new出來的內(nèi)存的釋放
class Smartpoint
{
public:
    Smartpoint(Person* p)
    {
        this->m_person = p;
    }
    //重載->運(yùn)算符
    Person* operator->()
    {
        return this->m_person;
    }
    //重載*運(yùn)算符
    Person& operator*()
    {
        return *m_person;
    }
    ~Smartpoint()
    {
        if (this->m_person != NULL)
        {
            //cout << "析構(gòu)函數(shù)調(diào)用" << endl;
            delete this->m_person;
        }
    }
private:
    Person* m_person;
};
int main()
{
    Smartpoint sp(new Person(18));
    sp->showage();
    (*sp).showage();
    return 0;
}

6.總結(jié)

在實(shí)際項(xiàng)目開發(fā)中建議使用智能指針,而非裸指針,這在后面的文章中會(huì)進(jìn)行具體的講解。

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

相關(guān)文章

  • C語言實(shí)現(xiàn)順序表的全操作詳解

    C語言實(shí)現(xiàn)順序表的全操作詳解

    順序表,全名順序存儲(chǔ)結(jié)構(gòu),是線性表的一種,線性表用于存儲(chǔ)邏輯關(guān)系為“一對(duì)一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對(duì)數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu)也有要求,跟隨下文來具體了解吧
    2022-04-04
  • 用C語言實(shí)現(xiàn)掃雷小游戲

    用C語言實(shí)現(xiàn)掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了用C語言實(shí)現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • OJ中G++和C++的區(qū)別

    OJ中G++和C++的區(qū)別

    今天小編就為大家分享一篇關(guān)于OJ中G++和C++的區(qū)別,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • C++中vector迭代器失效與深淺拷貝問題詳析

    C++中vector迭代器失效與深淺拷貝問題詳析

    迭代器失效就是迭代器底層對(duì)應(yīng)指針?biāo)赶虻目臻g倍銷毀了,導(dǎo)致使用了一塊已經(jīng)被釋放了的空間,下面這篇文章主要給大家介紹了C++中vector迭代器失效與深淺拷貝問題的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • 基于WTL 雙緩沖(double buffer)繪圖的分析詳解

    基于WTL 雙緩沖(double buffer)繪圖的分析詳解

    本篇文章是對(duì)WTL下使用雙緩沖(double buffer)繪圖進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言數(shù)據(jù)結(jié)構(gòu)實(shí)例講解單鏈表的實(shí)現(xiàn)

    C語言數(shù)據(jù)結(jié)構(gòu)實(shí)例講解單鏈表的實(shí)現(xiàn)

    單鏈表是后面要學(xué)的雙鏈表以及循環(huán)鏈表的基礎(chǔ),要想繼續(xù)深入了解數(shù)據(jù)結(jié)構(gòu)以及C++,我們就要奠定好這塊基石!接下來就和我一起學(xué)習(xí)吧
    2022-03-03
  • C語言實(shí)現(xiàn)掃雷項(xiàng)目

    C語言實(shí)現(xiàn)掃雷項(xiàng)目

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)掃雷項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++ 自定義控件的移植問題

    C++ 自定義控件的移植問題

    這篇文章主要介紹了C++ 自定義控件的移植問題,十分的簡單實(shí)用,有需要的小伙伴可以參考下。
    2015-06-06
  • C語言實(shí)現(xiàn)字符串字符反向排列的方法詳解

    C語言實(shí)現(xiàn)字符串字符反向排列的方法詳解

    這篇文章主要為大家分享了幾種通過C語言實(shí)現(xiàn)字符串字符反向排列(不是逆序打?。┑姆椒?,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-05-05
  • 詳解C語言之堆棧

    詳解C語言之堆棧

    這篇文章主要為大家介紹了C語言的堆棧,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11

最新評(píng)論