當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > C語言與CPP編程
[導(dǎo)讀]今天跟大家聊一下 BAT 面試 C++ 開發(fā)工程師必問的一個(gè)考點(diǎn):智能指針。

大家好,我是小牛,今天跟聊一下 BAT 面試 C++ 開發(fā)工程師必問的一個(gè)考點(diǎn):智能指針。

小艾:你昨晚面 C++ 去了?

小牛:對(duì)啊,不是這個(gè)廠主要技術(shù)棧都是 C++ 嘛,我就面去了。

小艾:?jiǎn)柫它c(diǎn)啥???

小牛:BAT 這 C++ 問的都差不多,又問智能指針了。

小艾:那來講講唄。

小牛:來。

智能指針的引入

大家都知道,指針是 C++ 中非常重要的一部分,大家在初期學(xué)習(xí) C++ 的時(shí)候一定學(xué)過類似這樣的指針方式。

int *ptr;

這種指針也被稱為裸指針。但是使用裸指針會(huì)存在一些不足

  1. 如果使用裸指針分配內(nèi)存后,忘記手動(dòng)釋放資源,會(huì)出現(xiàn)內(nèi)存泄漏。

  2. 如果使用多個(gè)裸指針指向同一資源,其中一個(gè)指針對(duì)資源進(jìn)行釋放,其它指針成為空懸指針,如果再次釋放會(huì)存在不可預(yù)測(cè)的錯(cuò)誤。上圖中當(dāng) sp1 把資源釋放后,sp2 成了空懸指針??諔抑羔樦傅氖侵羔?biāo)赶虻膶?duì)象已經(jīng)釋放的時(shí)候自身卻沒有被置為 nullptr。sp1 通過 free/delete釋放資源的內(nèi)存時(shí),內(nèi)存不會(huì)立刻被系統(tǒng)回收,而是狀態(tài)改變?yōu)榭杀黄渌胤缴暾?qǐng)的狀態(tài)。這時(shí)當(dāng)再次操作 sp2,這塊內(nèi)存可能被其它地方申請(qǐng)了,而具體被誰申請(qǐng)了是不確定的,因此可能導(dǎo)致的錯(cuò)誤也是不可預(yù)測(cè)的。

  3. 如果程序異常退出時(shí),裸指針的釋放資源的代碼未能執(zhí)行,也會(huì)造成內(nèi)存泄漏。

為了改善裸指針的不足,確保資源的分配和釋放是配對(duì)的,開發(fā)者提出了智能指針。智能指針主要是對(duì)裸指針進(jìn)行了一次面向?qū)ο蟮姆庋b,在構(gòu)造函數(shù)中初始化資源地址,在析構(gòu)函數(shù)中釋放資源。 當(dāng)資源應(yīng)該被釋放時(shí),指向它的智能指針可以確保自動(dòng)地釋放它。

C++ 庫(kù)中,為智能指針提供了不帶引用計(jì)數(shù)和帶引用計(jì)數(shù)的兩種方案。

引用計(jì)數(shù)用于表示有多少智能指針引用同一資源。不帶引用計(jì)數(shù)的智能指針采用獨(dú)占資源的方式,而帶引用計(jì)數(shù)的智能指針則可以同時(shí)多個(gè)指向同一資源。下面介紹一下它們的主要特點(diǎn)區(qū)別。

智能指針的分類

不帶引用計(jì)數(shù)的智能指針

不帶引用計(jì)數(shù)的智能指針包括 auto_ptr、scoped_ptr和 unique_ptr三種指針。

不帶引用計(jì)數(shù)的智能指針

1. auto_ptr:

我們先來看個(gè)例子:

#include int main() { auto_ptr<int> ptr(new int(6));//定義auto_ptr指針ptr auto_ptr<int> ptr1(ptr); //拷貝構(gòu)造ptr定義ptr1 *ptr=8;//對(duì)空指針ptr賦值會(huì)產(chǎn)生不可預(yù)料的錯(cuò)誤 return 0;
}

開始時(shí) ptr 指向資源,一個(gè)整型數(shù)字6,當(dāng)用 ptr1 拷貝構(gòu)造 ptr 時(shí),ptr1 指向資源,而 ptr 則指向 nullptr。下一行程序中如果對(duì)空指針 ptr 賦值 8,將會(huì)產(chǎn)生不可預(yù)料的錯(cuò)誤。

下圖表示 auto_ptr指針對(duì)資源的指向過程。

auto_ptr

使用拷貝構(gòu)造時(shí),如果只有最后一個(gè) auto_ptr持有資源,其余 auto_ptr持有的資源會(huì)被置為 nullptr。

因此需要注意,不能在容器中使用 auto_ptr,當(dāng)容器發(fā)生拷貝時(shí),原容器中 auto_ptr持有的資源會(huì)置 nullptr。

下面我們?cè)賮砜匆幌?auto_ptr的部分源碼和部分解析:

template<class _Ty> class auto_ptr { public: typedef _Ty?element_type; explicit auto_ptr(_Ty?*?_Ptr=nullptr) noexcept :?_Myptr(_Ptr)//初始化列表 { //構(gòu)造函數(shù) } auto_ptr(auto_ptr&?_Right) noexcept :?_Myptr(_Right.release())
??{ //拷貝構(gòu)造函數(shù),會(huì)調(diào)用release()函數(shù) } _Ty?* release() noexcept { /*使用拷貝構(gòu)造時(shí),最后一個(gè)auto_ptr持有資源,
???其余被置為nullptr*/ _Ty?*?_Tmp?=?_Myptr;
??_Myptr?= nullptr; return (_Tmp);
??} private:
?_Ty?*?_Myptr;//指向資源  };

當(dāng)試圖調(diào)用 auto_ptr的拷貝構(gòu)造函數(shù)時(shí),在初始化列表中調(diào)用了 release()函數(shù),release()函數(shù)用一個(gè) _Tmp指針保存資源并返回用于初始化當(dāng)前的 auto_ptr的類成員 _Myptr,而 _Right對(duì)應(yīng)的 _Myptr被置為 nullptr。

2. scoped_ptr

scoped_ptr和 auto_ptr有些不同,它私有化了拷貝構(gòu)造函數(shù)和賦值函數(shù),資源的所有權(quán)無法進(jìn)行轉(zhuǎn)移,也無法在容器中使用。

下面使用一段代碼表現(xiàn) scoped_ptr的特性,如果不規(guī)范使用會(huì)發(fā)生錯(cuò)誤。

正確用法:

scoped_ptr<int> sp1(new int(6));//初始化sp1指針 

錯(cuò)誤用法:

scoped_ptr<int> sp2(sp1);//錯(cuò)誤,無法拷貝構(gòu)造 

這種方法是錯(cuò)誤的,因?yàn)閟coped_ptr私有化了拷貝構(gòu)造函數(shù),無法顯式調(diào)用。

scoped_ptr<int> sp3(new int(5))//初始化sp2指針 sp1=sp3;//錯(cuò)誤,無法賦值 

這種方法是錯(cuò)誤的,因?yàn)閟coped_ptr私有化了賦值構(gòu)造函數(shù),無法顯式調(diào)用。

有時(shí)候面試官會(huì)問到,scoped_ptr是如何保證資源的所有權(quán)的?

這時(shí)候就可以按照上面的講解來回答:

scoped_ptr私有化了拷貝構(gòu)造函數(shù)和賦值函數(shù),資源的所有權(quán)無法進(jìn)行轉(zhuǎn)移,所以保證了資源的所有權(quán)。

然后再來看一下 scoped_ptr的部分源碼和部分解析:

template<class T> class scoped_ptr { private:
????T?*?px;?
????scoped_ptr(scoped_ptr const &);//拷貝構(gòu)造函數(shù) scoped_ptr?& operator=(scoped_ptr const &);//賦值構(gòu)造函數(shù) public: typedef T?element_type; explicit scoped_ptr(?T?*?p?= nullptr ): px(?p?) {
????}
????~scoped_ptr() //析構(gòu)函數(shù) };

scoped_ptr通過私有化拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)來拒絕淺拷貝的發(fā)生。

值得注意的是,auto_ptr是通過將除最后一個(gè)以外的其它 auto_ptr置 nullptr來避免淺拷貝的發(fā)生,它的資源所有權(quán)是可以轉(zhuǎn)移的。

scoped_ptr是直接禁止了拷貝與賦值,資源所有權(quán)無法轉(zhuǎn)移。

3. unique_ptr

unique_ptr刪除了拷貝構(gòu)造函數(shù)和賦值函數(shù),因此不支持普通的拷貝或賦值操作。如下所示:

unique_ptr<int> p1(new int(6));//正確寫法 unique_ptr<int> p2(p1); //這么寫是錯(cuò)誤的: //?unique_ptr不支持拷貝 unique_ptr<int>?p3;
p3=p2;//這么寫是錯(cuò)誤的:unique_ptr不支持賦值 

再來看一下 unique_ptr的部分源碼和部分解析:

template<class _Ty,class _Dx> class unique_ptr: public _Unique_ptr_base<_Ty, _Dx>
{ public: typedef _Unique_ptr_base<_Ty, _Dx>?_Mybase; typedef typename _Mybase::pointer?pointer; typedef _Ty?element_type; typedef _Dx?deleter_type; unique_ptr(unique_ptr&&?_Right) noexcept :?_Mybase(_Right.release(),
???_STD?forward(_Right.get_deleter()))
??{ //?右值引用的拷貝構(gòu)造函數(shù) } unique_ptr& operator=(unique_ptr&&?_Right) noexcept { //提供了右值引用的operator=賦值構(gòu)造函數(shù) if (this !=?_STD?addressof(_Right))
???{?
???reset(_Right.release()); this->get_deleter()?=?_STD?forward(_Right.get_deleter());
???} return (*this);
??} /*
?刪除了unique_ptr的拷貝構(gòu)造和賦值函數(shù),拒絕淺拷貝
?*/ unique_ptr(const unique_ptr&)?= delete; unique_ptr& operator=(const unique_ptr&)?= delete;
?};

unique_ptr和scoped_ptr一樣禁止了拷貝構(gòu)造和賦值構(gòu)造,引入了帶右值引用的拷貝構(gòu)造和賦值??梢园?unique_ptr作為函數(shù)的返回值。

不帶引用計(jì)數(shù)的智能指針總結(jié):

相同點(diǎn):最終只有一個(gè)智能指針持有資源。

不同點(diǎn):

  1. auto_ptr進(jìn)行拷貝構(gòu)造時(shí),會(huì)對(duì)之前的auto_ptr的資源置nullptr操作;
  2. scoped_ptr通過私有化了拷貝構(gòu)造和賦值函數(shù)杜絕淺拷貝;
  3. unique_ptr通過刪除了拷貝構(gòu)造和賦值函數(shù)函數(shù)杜絕淺拷貝,但引入了帶右值引用的拷貝構(gòu)造和賦值函數(shù)。

帶引用計(jì)數(shù)的智能指針

當(dāng)需要多個(gè)智能指針指向同一個(gè)資源時(shí),使用帶引用計(jì)數(shù)的智能指針。

每增加一個(gè)智能指針指向同一資源,資源引用計(jì)數(shù)加一,反之減一。當(dāng)引用計(jì)數(shù)為零時(shí),由最后一個(gè)指向資源的智能指針將資源進(jìn)行釋放。

下圖表示帶引用計(jì)數(shù)智能指針的工作過程。sp1 對(duì)象和 sp2 對(duì)象通過指針指向同一資源,引用計(jì)數(shù)器記錄了引用資源的對(duì)象個(gè)數(shù)。

智能指針的工作過程

當(dāng) sp1 對(duì)象發(fā)生析構(gòu)時(shí),引用計(jì)數(shù)器的值減 1,由于引用計(jì)數(shù)不等于 0,資源并未釋放,如下圖所示:

sp1 對(duì)象發(fā)生析構(gòu)

當(dāng) sp2 對(duì)象也發(fā)生析構(gòu),引用計(jì)數(shù)減為 0,資源釋放,如下圖所示:

sp2 對(duì)象也發(fā)生析構(gòu)

即引用計(jì)數(shù)可以保證多個(gè)智能指針指向資源時(shí)資源在所有智能對(duì)其取消引用再釋放,避免過早釋放產(chǎn)生空懸指針。帶引用計(jì)數(shù)的智能指針包括 shared_ptr和 weak_ptr。

資源釋放

1. shared_ptr

shared_ptr一般稱為強(qiáng)智能指針,一個(gè) shared_ptr對(duì)資源進(jìn)行引用時(shí),資源的引用計(jì)數(shù)會(huì)增加一,通常用于管理對(duì)象的生命周期。只要有一個(gè)指向?qū)ο蟮?shared_ptr存在,該對(duì)象就不會(huì)析構(gòu)。

上圖中引用計(jì)數(shù)的工作過程就使用了 shared_ptr。

2. weak_ptr

weak_ptr一般被稱為弱智能指針,其對(duì)資源的引用不會(huì)引起資源的引用計(jì)數(shù)的變化,通常作為觀察者,用于判斷資源是否存在,并根據(jù)不同情況做出相應(yīng)的操作。

比如使用 weak_ptr對(duì)資源進(jìn)行弱引用,當(dāng)調(diào)用 weak_ptr的 lock()方法時(shí),若返回 nullptr,則說明資源已經(jīng)不存在,放棄對(duì)資源繼續(xù)操作。否則,將返回一個(gè) shared_ptr對(duì)象,可以繼續(xù)操作資源。

另外,一旦最后一個(gè)指向?qū)ο蟮?shared_ptr被銷毀,對(duì)象就會(huì)被釋放。即使有 weak_ptr指向?qū)ο?,?duì)象也還是會(huì)被釋放。


小艾問:既然它這引用都不算數(shù),那它有什么用呢?

小牛答:別急,我們來慢慢講。


enable_shared_from_this 機(jī)制

小牛:考慮下面這樣一個(gè)場(chǎng)景:

在多線程環(huán)境中,假設(shè)有一個(gè)對(duì)象池類 ObjectPool和一個(gè)對(duì)象類 Object。ObjectPool類主要實(shí)現(xiàn)通過不同的 key 返回對(duì)應(yīng) Object 對(duì)象。

要求同一程序中由 Object 類實(shí)例出的不同對(duì)象只有一個(gè),即當(dāng)多處用到同一個(gè)對(duì)象,Object 對(duì)象應(yīng)該被共享。同時(shí)當(dāng)對(duì)象不再需要時(shí)應(yīng)該被析構(gòu),并刪除對(duì)應(yīng)的 key。

多線程應(yīng)用場(chǎng)景

小艾說:這還不簡(jiǎn)單,看我的。代碼刷的一下就寫完了。

//場(chǎng)景代碼 #include class ObjectPool:boost::noncopyable
{ public: shared_ptrget(const string&?key) { shared_ptrshObject; MutexLockGuard lock(mutex);
?weak_ptr&?wkObject=object[key];
?shObject=wkObject.lock(); //對(duì)象存在,提升成功并返回 if(!shObject){ /*對(duì)象不存在,提升失敗,shOject重新
??指向新創(chuàng)建的Object對(duì)象,
??并綁定回調(diào)函數(shù),讓對(duì)象Oject需要析構(gòu)時(shí)
??調(diào)用OjectPool對(duì)象的成員函數(shù)*/ shObject.reset(new Object(key),
????????????????????boost::bind(&
????????ObjectPool::deleteObject,this,
????????_1));
???????wkObject=shObject;
?} return shObject;
?} private: void deleteObject(Object*?obj) { /*回調(diào)函數(shù),在對(duì)象需要析構(gòu)時(shí)調(diào)用,從map中
?刪除對(duì)象和對(duì)應(yīng)的key*/ if(obj){ MutexLockGuard lock(mutex);
???object.erase(obj->key());
??} delete obj;
?} mutable MutexLock?mutex; std::map<string,weak_ptr>?object; /*map中不能使用shared_ptr,這會(huì)導(dǎo)致Oject對(duì)象永遠(yuǎn)不會(huì)被銷
?毀*/ };

小牛說:你這有問題?。?

小艾答:有什么問題?為了實(shí)現(xiàn) Object 類析構(gòu)時(shí)調(diào)用 ObjectPool的回調(diào)函數(shù),代碼中把 ObjectPool的 this 指針保存在了 boost::function處。

小牛說:那線程安全問題就來了。如果 ObjectPool先于 Object 對(duì)象析構(gòu),就會(huì)發(fā)生 core dump。因?yàn)?ObjectPool對(duì)象已經(jīng)不存在了,也就沒有辦法調(diào)用其成員方法。

小艾問:那怎么解決呢?

小牛說:簡(jiǎn)單啊,只需將 this 指針替換成指向當(dāng)前對(duì)象的 shared_ptr,從而保證在 Object 對(duì)象需要調(diào)用 ObjectPool::deleteObject時(shí) ObjectPool還活著。你要不試試實(shí)現(xiàn)一下?

小艾說:那我寫一個(gè)吧。

shared_ptr getSharedPtr() { return shared_ptr(this);?
}

小牛答:?jiǎn)栴}來了,在多線程環(huán)境中,在需要返回 this 對(duì)象時(shí)是無法得知對(duì)象的生存情況的。因此不能直接返回 this 對(duì)象

給你普及個(gè)解決方法吧,你可以通過繼承 enable_shared_from_this模板對(duì)象,然后調(diào)用從基類繼承而來的 shared_from_this方法來安全返回指向同一資源對(duì)象的 shared_ptr。

小艾:為什么繼承 enable_shared_from_this 模板對(duì)象就可以安全返回?

小牛:在回答你的問題前,我們先來講講 shared_ptr的構(gòu)造函數(shù)拷貝構(gòu)造函數(shù)對(duì)資源和引用計(jì)數(shù)影響的區(qū)別。

下面從 shared_ptr的實(shí)現(xiàn)原理來看:

shared_ptr從 _Ptr_base繼承了 element_type和 _Ref_count_base類型的兩個(gè)成員變量。

template<class _Ty> class _Ptr_base { private:
?element_type?*?_Ptr{nullptr}; //?指向資源的指針 _Ref_count_base?*?_Rep{nullptr}; //?指向資源引用計(jì)數(shù)的指針 };

_Ref_count_base中定義了原子類型的變量 _Uses和 _Weaks,它們分別記錄資源的引用個(gè)數(shù)和資源觀察者的個(gè)數(shù)。

class __declspec(novtable)?_Ref_count_base { private:
?_Atomic_counter_t?_Uses;//記錄資源引用個(gè)數(shù) _Atomic_counter_t?_Weaks;//記錄觀察者個(gè)數(shù) }

當(dāng)要使用 shared_ptr管理同一資源,調(diào)用 shared_ptr的構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù)是不一樣的,它們雖然使得不同 shared_ptr指向同一資源,但管理引用計(jì)數(shù)資源的方式卻不一樣。

下面給出兩個(gè) shared_ptr管理同一資源(A對(duì)象)使用不同構(gòu)造函數(shù)對(duì)引用計(jì)數(shù)對(duì)象的影響。

方式1:調(diào)用構(gòu)造函數(shù)

class A { public:
??A(){}
??~A(){}
};
A?*p?= new A(); shared_ptr ptr1(p);//調(diào)用構(gòu)造函數(shù) shared_ptr ptr2(p);//調(diào)用構(gòu)造函數(shù) 
方式1:調(diào)用構(gòu)造函數(shù)

如上圖所示,方式1中 ptr1 和 ptr2 都調(diào)用了 shared_ptr的構(gòu)造函數(shù),該構(gòu)造方式使得 ptr1和 ptr2都開辟了自已的引用資源對(duì)象 _Ref_count_base,即 _Ref_count_base有兩個(gè),都記錄了 A 對(duì)象的引用計(jì)數(shù)為 1,析構(gòu)時(shí) ptr1和 ptr2的引用計(jì)數(shù)各自減為 1,導(dǎo)致 A 對(duì)象析構(gòu)兩次,出現(xiàn)邏輯錯(cuò)誤。

方式2:調(diào)用拷貝構(gòu)造函數(shù)

class A { public:
???A(){}
???~A(){}
}
A?*p?= new A(); shared_ptr ptr1(p);//調(diào)用構(gòu)造函數(shù) shared_ptr ptr2(ptr1);//調(diào)用拷貝構(gòu)造函數(shù) 
方式2:調(diào)用拷貝構(gòu)造函數(shù)

如上圖所示,方式2中由于 ptr2拷貝構(gòu)造 ptr1,它們引用的 _Ref_count_base是同一個(gè),因此引用計(jì)數(shù)為 2,析構(gòu)的時(shí)候 A 對(duì)象只析構(gòu)一次,正常運(yùn)行。

在明白了 shared_ptr構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù)的做的事情不同后,就能理解當(dāng)需要返回一個(gè)需要 shared_ptr管理的對(duì)象為什么不能寫成 return shared_ptr< A >(this)了。

小艾:說的沒錯(cuò),因?yàn)檫@樣會(huì)調(diào)用 shared_ptr的構(gòu)造函數(shù),對(duì)于 this 對(duì)象再創(chuàng)建一個(gè)新的引用計(jì)數(shù)對(duì)象,從而導(dǎo)致對(duì)象多次析構(gòu)而出現(xiàn)邏輯錯(cuò)誤。

小牛:再給你深入講講 enable_shared_from_this的實(shí)現(xiàn)機(jī)制。

如下所示,enable_shared_from_this類中包含一個(gè)作為觀察者的成員變量。

template<class _Ty> class enable_shared_from_this { public: mutable weak_ptr_Wptr;//指向資源 };

當(dāng)一個(gè)類繼承了 enable_shared_from_this類,就繼承了 _Wptr這個(gè)成員變量。

當(dāng)使用 shared_ptr< A >(new A())第一次構(gòu)造智能指針對(duì)象時(shí),就會(huì)初始化一個(gè)作為觀察者的弱智能指針 _Wptr指向A對(duì)象資源。

再通過 shared_from_this()方法代替 shared_ptr的普通構(gòu)造函數(shù)來返回一個(gè) shared_ptr對(duì)象,從而避免產(chǎn)生額外的引用計(jì)數(shù)對(duì)象。

shared_ptr getSharedPtr() { return shared_from_this();?
}

shared_from_this函數(shù)中,主要嘗試將弱智能指針提升為強(qiáng)智能指針來返回一個(gè) shared_ptr對(duì)象。

這樣還能在多線程環(huán)境中判斷對(duì)象是否存活,存活即提升成功,安全返回。如果對(duì)象已經(jīng)析構(gòu),則放棄提升,即起到了保證線程安全的作用。

小牛:了解了enable_shared_from_this,要不再試試改代碼?

小艾:那我來改一下之前的代碼。

第一處修改:

class ObjectPool:boost::noncopyable //為 class ObjectPool:public boost::enable_shared_from_this,
????????????????boost::noncopyable
{/*...*/};

第二處修改:

//改變 shared_ptrget(const string&?key) { /*...*/ shObject.reset(new Object(key),
?????????????????????boost::bind(&ObjectPool::deleteObject,this,_1)); /*...*/ } //為 shared_ptrget(const string&?key) { /*...*/ shObject.reset(new Object(key),
?????????????????????boost::bind(&ObjectPool::deleteObject,shared_from_this(),_1)); /*...*/ }

完整代碼:

#include class ObjectPool:public boost::enable_shared_from_this,
????????????????boost::noncopyable
{ public: shared_ptrget(const string&?key) { shared_ptrshObject; MutexLockGuard lock(mutex);
???weak_ptr&?wkObject=object[key];
???shObject=wkObject.lock();//對(duì)象存在,提升成功并返回 if(!shObject){ /*對(duì)象不存在,提升失敗,shOject重新指向新創(chuàng)建的
????Object對(duì)象,并綁定回調(diào)函數(shù),讓對(duì)象Oject需要析構(gòu)時(shí)
????調(diào)用OjectPool對(duì)象的成員函數(shù)*/ shObject.reset(new Object(key),
??????????????????????boost::bind(&
??????????ObjectPool::deleteObject,shared_from_this(),
??????????_1));
??????wkObject=shObject;
???} return shObject;
} private: void deleteObject(Object*?obj) { /*回調(diào)函數(shù),在對(duì)象需要析構(gòu)時(shí)調(diào)用,從map中刪除對(duì)象和對(duì)
應(yīng)的key*/ if(obj){ MutexLockGuard lock(mutex);
?????object.erase(obj->key());
????} delete obj;
} mutable MutexLock?mutex; std::map<string,weak_ptr>?object; /*map中不能使用shared_ptr,這會(huì)導(dǎo)致Oject對(duì)象永遠(yuǎn)不會(huì)被銷
毀*/ };

小牛:不錯(cuò)不錯(cuò),這下懂了 shared_ptr和 weak_ptr結(jié)合的用法了吧。

帶引用計(jì)數(shù)智能指針總結(jié):

  1. shared_ptr會(huì)增加資源的引用計(jì)數(shù),常用于管理對(duì)象的生命周期。
  2. weak_ptr不會(huì)增加資源的引用計(jì)數(shù),常作為觀察者用來判斷對(duì)象是否存活。
  3. 使用 shared_ptr的普通拷貝構(gòu)造函數(shù)會(huì)產(chǎn)生額外的引用計(jì)數(shù)對(duì)象,可能導(dǎo)致對(duì)象多次析構(gòu)。使用 shared_ptr的拷貝構(gòu)造函數(shù)則只影響同一資源的同一引用計(jì)數(shù)的增減。
  4. 當(dāng)需要返回指向當(dāng)前對(duì)象的 shared_ptr時(shí),優(yōu)先使用 enable_shared_from_this機(jī)制。

總結(jié)

今天我們了解了面試中常常會(huì)問到的C++ 智能指針的相關(guān)知識(shí)點(diǎn),結(jié)合源碼和示例理清各種智能指針的特點(diǎn)。

并且結(jié)合一個(gè)實(shí)際的多線程應(yīng)用場(chǎng)景,講解了enable_shared_from_this 機(jī)制,希望能對(duì)大家的學(xué)習(xí)有所幫助。

總結(jié)

參考

  1. https://blog.csdn.net/qiangweiyuan/article/details/88562935
  2. 《Linux多線程服務(wù)端編程使用muduo C++ 網(wǎng)絡(luò)庫(kù)》
  3. 《C++ Primer》
  4. 《More Effective C++》

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉