在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C++中的智能指針

電子工程師 ? 來源:C語言與CPP編程 ? 作者:C語言與CPP編程 ? 2022-08-05 11:11 ? 次閱讀

大家好,今天借助本文,從實踐、避坑和實現原理三個角度分析下C++中的智能指針。

本文主要內容如下圖所示:

3490e1c0-1463-11ed-ba43-dac502259ad0.png

智能指針的由來

auto_ptr為什么被廢棄

unique_ptr的使用、特點以及實現

shared_ptr的使用、特點以及實現

weak_ptr的使用、特點以及實現

介紹筆者在工作中遇到的一些職能指針相關的坑,并給出一些建議

背景

內存的分配與回收都是由開發人員在編寫代碼時主動完成的,好處是內存管理的開銷較小,程序擁有更高的執行效率;弊端是依賴于開發者的水平,隨著代碼規模的擴大,極容易遺漏釋放內存的步驟,或者一些不規范的編程可能會使程序具有安全隱患。如果對內存管理不當,可能導致程序中存在內存缺陷,甚至會在運行時產生內存故障錯誤。換句話說,開發者自己管理內存,最容易發生下面兩種情況:

申請了內存卻沒有釋放,造成內存泄漏

使用已經釋放的內存,造成segment fault

所以,為了在保證性能的前提下,又能使得開發者不需要關心內存的釋放,進而使得開發者能夠將更多的精力投入到業務上,自C++11開始,STL正式引入了智能指針。

所有權

智能指針一個很關鍵的一個點就是是否擁有一個對象的所有權,當我們通過std::make_xxx或者new一個對象,那么就擁有了這個對象的所有權。

所有權分為獨占所有權、共享所有權以及弱共享所有權三種。

獨占所有權

顧名思義,獨占該對象。獨占的意思就是不共享,所有權可以轉移,但是轉移之后,所有權也是獨占。auto_ptr和unique_ptr就是一種獨占所有權方式的智能指針。

假設有個Object對象,如果A擁有該對象的話,就需要保證其在不使用該對象的時候,將該對象釋放;而此時如果B也想擁有Object對象,那么就必須先讓A放棄該對象所有權,然后B獨享該對象,那么該對象的使用和釋放就只歸B所有,跟A沒有關系了。

獨占所有權具有以下幾個特點:

如果創建或者復制了某個對象,就擁有了該對象

如果沒有創建對象,而是將對象保留使用,同樣擁有該對象的所有權

如果你擁有了某個對象的所有權,在不需要某一個對象時,需要釋放它們

共享所有權

共享所有權,與獨占所有權正好相反,對某個對象的所有權可以共享。shared_ptr就是一種共享所有權方式的智能指針。

假設此時A擁有對象Object,在沒有其它擁有該對對象的情況下,對象的釋放由A來負責;如果此時B也想擁有該對象,那么對象的釋放由最后一個擁有它的來負責。

舉一個我們經常遇到的例子,socket連接,多個發送端(sender)可以使用其發送和接收數據。

34a87fe2-1463-11ed-ba43-dac502259ad0.png

弱共享所有權

弱共享所有權,指的是可以使用該對象,但是沒有所有權,由真正擁有其所有權的來負責釋放。weak_ptr就是一種弱共享所有權方式的智能指針。

34c2be70-1463-11ed-ba43-dac502259ad0.png

分類

在C++11中,有unique_ptr、shared_ptr以及weak_ptr三種,auto_ptr因為自身轉移所有權的原因,在C++11中被廢棄(本節最后,將簡單說下被廢棄的原因)。

unique_ptr

使用上限制最多的一種智能指針,被用來取代之前的auto_ptr,一個對象只能被一個unique_ptr所擁有,而不能被共享,如果需要將其所擁有的對象轉移給其他unique_ptr,則需要使用move語義

shared_ptr

與unique_ptr不同的是,unique_ptr是獨占管理權,而shared_ptr則是共享管理權,即多個shared_ptr可以共用同一塊關聯對象,其內部采用的是引用計數,在拷貝的時候,引用計數+1,而在某個對象退出作用域或者釋放的時候,引用計數-1,當引用計數為0的時候,會自動釋放其管理的對象。

weak_ptr

weak_ptr的出現,主要是為了解決shared_ptr的循環引用,其主要是與shared_ptr一起來使用。和shared_ptr不同的地方在于,其并不會擁有資源,也就是說不能訪問對象所提供的成員函數,不過,可以通過weak_ptr.lock()來產生一個擁有訪問權限的shared_ptr。

auto_ptr

auto_ptr自C++98被引入,因為其存在較多問題,所以在c++11中被廢棄,自C++17開始正式從STL中移除。

首先我們看下auto_ptr的簡單實現(為了方便閱讀,進行了修改,基本功能類似于std::auto_ptr):

template
classauto_ptr
{
T*p;
public:
auto_ptr(T*s):p(s){}
~auto_ptr(){deletep;}

auto_ptr(auto_ptr&a){
p=a.p;
a.p=NULL;
}
auto_ptr&operator=(auto_ptr&a){
deletep;
p=a.p;
a.p=NULL;
return*this;
}

T&operator*()const{return*p;}
T*operator->()const{returnp;}
};

從上面代碼可以看出,auto_ptr采用copy語義來轉移所有權,轉移之后,其關聯的資源指針設置為NULL,而這跟我們理解上copy行為不一致。

在<< Effective STL >>第8條,作者提出永不建立auto_ptr的容器,并以一個例子來說明原因,感興趣的可以去看看這本書,還是不錯的。

實際上,auto_ptr被廢棄的直接原因是拷貝造成所有權轉移,如下代碼:

auto_ptra(newClassA);
auto_ptrb=a;
a->Method();

在上述代碼中,因為b = a導致所有權被轉移,即a關聯的對象為NULL,如果再調用a的成員函數,顯然會造成coredump。

正是因為拷貝導致所有權被轉移,所以auto_ptr使用上有很多限制:

不能在STL容器中使用,因為復制將導致數據無效

一些STL算法也可能導致auto_ptr失效,比如std::sort算法

不能作為函數參數,因為這會導致復制,并且在調用后,導致原數據無效

如果作為類的成員變量,需要注意在類拷貝時候導致的數據無效

正是因為auto_ptr的諸多限制,所以自C++11起,廢棄了auto_ptr,引入unique_ptr。

unique_ptr

unique_ptr是C++11提供的用于防止內存泄漏的智能指針中的一種實現(用來替代auto_ptr),獨享被管理對象指針所有權的智能指針。

unique_ptr對象包裝一個原始指針,并負責其生命周期。當該對象被銷毀時,會在其析構函數中刪除關聯的原始指針。具有->和*運算符重載符,因此它可以像普通指針一樣使用。

分類

unique_ptr分為以下兩種:

指向單個對象

std::unique_ptrp1;//p1關聯Type對象

指向一個數組

unique_ptrp2;//p2關聯Type對象數組

特點

在前面的內容中,我們已經提到了unique_ptr的特點,主要具有以下:

獨享所有權,在作用域結束時候,自動釋放所關聯的對象

voidfun(){
unique_ptra(newint(1));
}

無法進行拷貝與賦值操作

unique_ptrptr(newint(1));
unique_ptrptr1(ptr);//error
unique_ptrptr2=ptr;//error

顯示的所有權轉移(通過move語義)

unique_ptrptr(newint(1));
unique_ptrptr1=std::move(ptr);//ok

作為容器元素存儲在容器中

unique_ptrptr(newint(1));
std::vector>v;

v.push_back(ptr);//error
v.push_back(std::move(ptr));//ok

std::cout<

需要注意的是,自c++14起,可以使用下面的方式對unique_ptr進行初始化:

autop1=std::make_unique(3.14);
autop2=std::make_unique(n);

如果在c++11中使用上述方法進行初始化,會得到下面的錯誤提示:

error:‘make_unique’isnotamemberof‘std’

因此,如果為了使得c++11也可以使用std::make_unique,我們可以自己進行封裝,如下:

namespacedetails{

#if__cplusplus>=201402L//C++14及以后使用STL實現的
usingstd::make_unique;
#else
template
std::unique_ptrmake_unique(Args&&...args)
{
returnstd::unique_ptr(newT(std::forward(args)...));
}
#endif
}//namespacedetails

使用

為了盡可能了解unique_ptr的使用姿勢,我們使用以下代碼為例:

#include
#include//std::move

voidfun1(double*);
voidfun2(std::unique*);
voidfun3(std::unique&);
voidfun4(std::unique);

intmain(){
std::unique_ptrp(newdouble(3.14));

fun1(p.get());
fun2(&p);
fun3(p);

if(p){
std::cout<

上述代碼,基本覆蓋了常見的unique_ptr用法:

第10行,通過new創建一個unique_ptr對象

第11行,通過get()函數獲取其關聯的原生指針

第12行,通過unique_ptr對象的指針進行訪問

第13行,通過unique_ptr對象的引用進行訪問

第16行,通過if(p)來判斷其是否有效

第18行,通過release函數釋放所有權,并將所有權進行轉移

第19行,通過reset釋放之前的原生指針,并重新關聯一個新的指針

第20行,通過std::move轉移所有權

簡單實現

本部分只是基于源碼的一些思路,便于理解,實現的一個簡單方案,如果想要閱讀源碼,請點擊unique_ptr查看。

基本代碼如下:

template
classunique_ptr
{
T*p;
public:
unique_ptr():p(){}
unique_ptr(T*s):p(s){}
~unique_ptr(){deletep;}

unique_ptr(constunique_ptr&)=delete;
unique_ptr&operator=(constunique_ptr&)=delete;

unique_ptr(unique_ptr&&s):p(s.p){s.p=nullptr}

unique_ptr&operator=(unique_ptrs)
{deletep;p=s.p;s.p=nullptr;return*this;}

T*operator->()const{returnp;}
T&operator*()const{return*p;}
};

從上面代碼基本可以看出,unique_ptr的控制權轉移是通過move語義來實現的,相比于auto_ptr的拷貝語義轉移所有權,更為合理。

shared_ptr

unique_ptr因為其局限性(獨享所有權),一般很少用于多線程操作。在多線程操作的時候,既可以共享資源,又可以自動釋放資源,這就引入了shared_ptr。

shared_ptr為了支持跨線程訪問,其內部有一個引用計數(線程安全),用來記錄當前使用該資源的shared_ptr個數,在結束使用的時候,引用計數為-1,當引用計數為0時,會自動釋放其關聯的資源。

特點

相對于unique_ptr的獨享所有權,shared_ptr可以共享所有權。其內部有一個引用計數,用來記錄共享該資源的shared_ptr個數,當共享數為0的時候,會自動釋放其關聯的資源。

shared_ptr不支持數組,所以,如果用shared_ptr指向一個數組的話,需要自己手動實現deleter,如下所示:

std::shared_ptrp(newint[8],[](int*ptr){delete[]ptr;});

使用

仍然以一段代碼來說明,畢竟代碼更有說服力。

#include
#include

intmain(){
//創建shared_ptr對象
std::shared_ptrp1=std::make_shared();
*p1=78;
std::cout<p2(p1);
//打印引用計數
std::cout<

輸出如下:

p1=78
p1Referencecount=1
p2Referencecount=2
p1Referencecount=2
p1andp2arepointingtosamepointer
Resetp1
p1ReferenceCount=0
p1ReferenceCount=1
p1ReferenceCount=0
p1isNULL

上面代碼基本羅列了shared_ptr的常用方法,對于其他方法,可以參考源碼或者官網。

線程安全

可能很多人都對shared_ptr是否線程安全存在疑惑,借助本節,對線程安全方面的問題進行分析和解釋。

shared_ptr的線程安全問題主要有以下兩種:

引用計數的加減操作是否線程安全

shared_ptr修改指向時是否線程安全

引用計數

shared_ptr中有兩個指針,一個指向所管理數據的地址,另一個一個指向執行控制塊的地址。

執行控制塊包括對關聯資源的引用計數以及弱引用計數等。在前面我們提到shared_ptr支持跨線程操作,引用計數變量是存儲在堆上的,那么在多線程的情況下,指向同一數據的多個shared_ptr在進行計數的++或--時是否線程安全呢?

引用計數在STL中的定義如下:

_Atomic_word_M_use_count;//#shared
_Atomic_word_M_weak_count;//#weak+(#shared!=0)

當對shared_ptr進行拷貝時,引入計數增加,實現如下:

template<>
inlinevoid
_Sp_counted_base<_S_atomic>::
_M_add_ref_lock(){
//Performlock-freeadd-if-not-zerooperation.
_Atomic_word__count;
do
{
__count=_M_use_count;
if(__count==0)
__throw_bad_weak_ptr();
}
while(!__sync_bool_compare_and_swap(&_M_use_count,__count,
__count+1));
}

最終,計數的增加,是調用__sync_bool_compare_and_swap實現的,而該函數是線程安全的,因此我們可以得出結論:在多線程環境下,管理同一個數據的shared_ptr在進行計數的增加或減少的時候是線程安全的,這是一波原子操作。

修改指向

修改指向分為操作同一個對象和操作不同對象兩種。

同一對象

以下面代碼為例:

voidfun(shared_ptr&p){
if(...){
p=p1;
}else{
p=p2;
}
}

當在多線程場景下調用該函數時候,p之前的引用計數要進行-1操作,而p1對象的引用計數要進行+1操作,雖然這倆的引用計數操作都是線程安全的,但是對這倆對象的引用計數的操作在一起時候卻不是線程安全的。這是因為當對p1的引用計數進行+1時候,恰恰前一時刻,p1的對象被釋放,后面再進行+1操作,會導致segment fault。

不同對象

代碼如下:

voidfun1(std::shared_ptr&p){
p=p1;
}

voidfun2(std::shared_ptr&p){
p=p2;
}

intmain(){
std::shared_ptrp=std::make_shared();
autop1=p;
autop2=p;
std::threadt1(fun1,p1);
std::threadt2(fun2,p2);

t1.join();
t2.join();

return0;
}

在上述代碼中,p、p1、p2指向同一個資源,分別有兩個線程操作不同的shared_ptr對象(雖然關聯的底層資源是同一個),這樣在多線程下,只對p1和p2的引用計數進行操作,不會引起segment fault,所以是線程安全的。

?

同一個shared_ptr被多個線程同時讀是安全的

同一個shared_ptr被多個線程同時讀寫是不安全的

?

簡單實現

本部分只是基于源碼的一些思路,便于理解,實現的一個簡單方案,如果想要閱讀源碼,請點擊shared_ptr查看。

記得之前看過一個問題為什么引用計數要new,這個問題我在面試的時候也問過,很少有人能夠回答出來,其實,很簡單,因為要支持多線程訪問,所以只能要new呀。

代碼如下:

template
classweak_ptr;

classCounter{
public:
Counter()=default;
ints_=0;//shared_ptr的計數
intw_=0;//weak_ptr的計數
};

template
classshared_ptr{
public:
shared_ptr(T*p=0):ptr_(p){
cnt_=newCounter();
if(p){
cnt_->s_=1;
}
}

~shared_ptr(){
release();
}

shared_ptr(shared_ptrconst&s){
ptr_=s.ptr_;
(s.cnt)->s_++;
cnt_=s.cnt_;
}

shared_ptr(weakptr_const&w){
ptr_=w.ptr_;
(w.cnt_)->s_++;
cnt_=w.cnt_;
}

shared_ptr&operator=(shared_ptr&s){
if(this!=&s){
release();
(s.cnt_)->s_++;
cnt_=s.cnt_;
ptr_=s.ptr_;
}
return*this;
}

T&operator*(){
return*ptr_;
}

T*operator->(){
returnptr_;
}

friendclassweak_ptr;

protected:
voidrelease(){
cnt_->s_--;
if(cnt_->s_w_

weak_ptr

在三個智能指針中,weak_ptr是存在感最低的一個,也是最容易被大家忽略的一個智能指針。它的引入是為了解決shared_ptr存在的一個問題循環引用。

特點

不具有普通指針的行為,沒有重載operator*和operator->

沒有共享資源,它的構造不會引起引用計數增加

用于協助shared_ptr來解決循環引用問題

可以從一個shared_ptr或者另外一個weak_ptr對象構造,進而可以間接獲取資源的弱共享權。

使用

intmain(){
std::shared_ptrp1=std::make_shared(14);
{
std::weak_ptrweak=p1;
std::shared_ptrnew_shared=weak.lock();

shared_e1=nullptr;

new_shared=nullptr;
if(weak.expired()){
std::cout<

上述代碼輸出如下:

weakpointerisexpired
0

使用成員函數use_count()和expired()來獲取資源的引用計數,如果返回為0或者false,則表示關聯的資源不存在

使用lock()成員函數獲得一個可用的shared_ptr對象,進而操作資源

當expired()為true的時候,lock()函數將返回一個空的shared_ptr

簡單實現

template
classweak_ptr
{
public:
weak_ptr()=default;

weak_ptr(shared_ptr&s):ptr_(s.ptr_),cnt(s.cnt_){
cnt_->w_++;
}

weak_ptr(weak_ptr&w):ptr_(w.ptr_),cnt_(w.cnt_){
cnt_->w_++;
}
~weak_ptr(){
release();
}
weak_ptr&operator=(weak_ptr&w){
if(this!=&w){
release();
cnt_=w.cnt_;
cnt_->w_++;
ptr_=w.ptr_;
}
return*this;
}
weak_ptr&operator=(shared_ptr&s)
{
release();
cnt_=s.cnt_;
cnt_->w_++;
ptr_=s.ptr_;
return*this;
}

shared_ptrlock(){
returnshared_ptr(*this);
}

boolexpired(){
if(cnt){
if(cnt->s_>0){
returnfalse;
}
}
returntrue;
}

friendclassshared_ptr;

protected:
voidrelease(){
if(cnt_){
cnt_->w_--;
if(cnt_->w_s_

循環引用

在之前的文章內存泄漏-原因、避免以及定位中,我們講到使用weak_ptr來配合shared_ptr使用來解決循環引用的問題,借助本文,我們深入說明下如何來解決循環引用的問題。

代碼如下:

classController{
public:
Controller()=default;

~Controller(){
std::cout<controller_;
};

std::shared_ptrsub_controller_;
};

在上述代碼中,因為controller和sub_controller之間都有一個指向對方的shared_ptr,這樣就導致任意一個都因為對方有一個指向自己的對象,進而引用計數不能為0。

34d2eb24-1463-11ed-ba43-dac502259ad0.png

為了解決std::shared_ptr循環引用導致的內存泄漏,我們可以使用std::weak_ptr來單面去除上圖中的循環。

classController{
public:
Controller()=default;

~Controller(){
std::cout<controller_;
};

std::shared_ptrsub_controller_;
};

在上述代碼中,我們將SubController類中controller_的類型從std::shared_ptr變成std::weak_ptr。

34e5e008-1463-11ed-ba43-dac502259ad0.png

那么,為什么將SubController中的shared_ptr換成weak_ptr就能解決這個問題呢?我們看下源碼:

template
__weak_ptr&
operator=(const__shared_ptr<_Tp1,?_Lp>&__r)//neverthrows
{
_M_ptr=__r._M_ptr;
_M_refcount=__r._M_refcount;
return*this;
}

在上面代碼中,我們可以看到,將一個shared_ptr賦值給weak_ptr的時候,其引用計數并沒有+1,所以也就解決了循環引用的問題。

那么,如果我們想要使用shared_ptr關聯的對象進行操作時候,該怎么做呢?使用weak_ptr::lock()函數來實現,源碼如下:

__shared_ptr<_Tp,?_Lp>
lock()const{
returnexpired()?__shared_ptr():__shared_ptr(*this);
}

從上面代碼可看出,使用lock()函數生成一個shared_ptr供使用,如果之前的shared_ptr已經被釋放,那么就返回一個空shared_ptr對象,否則生成shared_ptr對象的拷貝(這樣即使之前的釋放也不會存在問題)。

經驗之談

不要混用

指針之間的混用,有時候會造成不可預知的錯誤,所以建議盡量不要混用。包括裸指針和智能指針以及智能指針之間的混用

裸指針和智能指針混用

代碼如下:

voidfun(){
autoptr=newType;
std::shared_ptrt(ptr);

deleteptr;
}

在上述代碼中,將ptr所有權歸shared_ptr所擁有,所以在出fun()函數作用域的時候,會自動釋放ptr指針,而在函數末尾又主動調用delete來釋放,這就會造成double delete,會造成segment fault。

智能指針混用

代碼如下:

voidfun(){
std::unique_ptrt(newType);
std::shared_ptrt1(t.get());
}

在上述代碼中,將t關聯的對象又給了t1,也就是說同一個對象被兩個智能指針所擁有,所以在出fun()函數作用域的時候,二者都會釋放其關聯的對象,這就會造成double delete,會造成segment fault。

需要注意的是,下面代碼在STL中是支持的:

voidfun(){
std::unique_ptrt(newType);
std::shared_ptrt1(std::move(t));
}

不要管理同一個裸指針

代碼如下:

voidfun(){
autoptr=newType;
std::unique_ptrt(ptr);
std::shared_ptrt1(ptr);
}

在上述代碼中,ptr所有權同時給了t和t1,也就是說同一個對象被兩個智能指針所擁有,所以在出fun()函數作用域的時候,二者都會釋放其關聯的對象,這就會造成double delete,會造成segment fault。

避免使用get()獲取原生指針

voidfun(){
autoptr=std::make_shared();

autoa=ptr.get();

std::shared_ptrt(a);
deletea;
}

一般情況下,生成的指針都要顯式調用delete來進行釋放,而上述這種,很容易稍不注意就調用delete;非必要不要使用get()獲取原生指針。

不要管理this指針

classType{
private:
voidfun(){
std::shared_ptrt(this);
}
};

在上述代碼中,如果Type在棧上,則會導致segment fault,堆上視實際情況(如果在對象在堆上生成,那么使用合理的話,是允許的)。

只管理堆上的對象

voidfun(){
Typet;
std::shared_ptrptr(&t);
};

在上述代碼中,t在棧上進行分配,在出作用域的時候,會自動釋放。而ptr在出作用域的時候,也會調用delete釋放t,而t本身在棧上,delete一個棧上的地址,會造成segment fault。

優先使用unique_ptr

根據業務場景,如果需要資源獨占,那么建議使用unique_ptr而不是shared_ptr,原因如下:

性能優于shared_ptr

因為shared_ptr在拷貝或者釋放時候,都需要操作引用計數

內存占用上小于shared_ptr

shared_ptr需要維護它指向的對象的線程安全引用計數和一個控制塊,這使得它比unique_ptr更重量級

使用make_shared初始化

我們看下常用的初始化shared_ptr兩種方式,代碼如下:

std::shared_ptrp1=newType;
std::shared_ptrp2=std::make_shared();

那么,上述兩種方法孰優孰劣呢?我們且從源碼的角度進行分析。

第一種初始化方法,有兩次內存分配:

new Type分配對象

為p1分配控制塊(control block),控制塊用于存放引用計數等信息

我們再看下make_shared源碼:

templateinline
shared_ptr<_Ty>make_shared(_Types&&..._Args)
{//makeashared_ptr
_Ref_count_obj<_Ty>*_Rx=
new_Ref_count_obj<_Ty>(_STDforward<_Types>(_Args)...);

shared_ptr<_Ty>_Ret;
_Ret._Resetp0(_Rx->_Getptr(),_Rx);
return(_Ret);
}

這里的_Ref_count_obj類包含成員變量:

控制塊

一個內存塊,用于存放智能指針管理的資源對象

再看看_Ref_count_obj的構造函數:

template
_Ref_count_obj(_Types&&..._Args)
:_Ref_count_base()
{//constructfromargumentlist
::new((void*)&_Storage)_Ty(_STDforward<_Types>(_Args)...);
}

此處雖然也有一個new操作,但是此處是placement new,所以不存在內存申請。

從上面分析我們可以看出,第一種初始化方式(new方式)共有兩次內存分配操作,而第二種初始化方式(make_shared)只有一次內存申請,所以建議使用make_shared方式進行初始化。

結語

智能指針的出現,能夠使得開發者不需要關心內存的釋放,進而使得開發者能夠將更多的精力投入到業務上。但是,因為智能指針本身也有其局限性,如果使用不當,會造成意想不到的后果,所以,在使用之前,需要做一些必要的檢查,為了更好地用好智能指針,建議看下源碼實現,還是比較簡單的。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4331

    瀏覽量

    62622
  • C++
    C++
    +關注

    關注

    22

    文章

    2108

    瀏覽量

    73654
  • 代碼
    +關注

    關注

    30

    文章

    4788

    瀏覽量

    68617

原文標題:智能指針-使用、避坑和實現

文章出處:【微信號:C語言與CPP編程,微信公眾號:C語言與CPP編程】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    淺談C/C++里的指針

    指針CC++的難點和重點。指針C的靈魂。我不想重復大多數書上說得很清楚的東西,只是把我看
    發表于 06-28 10:21 ?428次閱讀

    關于C++函數指針的使用

    關于C++函數指針的使用(包含對typedef用法的討論) (一)簡單的函數指針的應用。 //形式1:返回類型(*函數名)(參數表) char (*pFun)(int); c
    發表于 07-13 03:51

    嵌入式工程師需要哪些技能書/技能加點

    程師嵌入式硬件工程師通用技能樹軟件C/C++語言編程經驗、編程能力、應用開發、OOP面向對象編程方式、軟件框架、C指針、文件IO、進程線程、高級IO、對
    發表于 08-06 09:46

    華為內部員工培訓資料-C++課件

     C++語言中級教材講授C++語言的運用技術,包括:類、對象之間的關系、對象的存儲與布局、運算符重載、智能指針、仿函數、泛型編程,C++模式設計基本思想。 目 &
    發表于 10-16 14:10 ?0次下載
    華為內部員工培訓資料-<b class='flag-5'>C++</b>課件

    C指針_CC++經典著作

    C指針_CC++經典著作,感興趣的小伙伴們可以瞧一瞧。
    發表于 11-16 18:32 ?0次下載

    C++實驗--指針

    C++實驗--指針
    發表于 12-30 14:50 ?1次下載

    C++指針”學習建議

    C++指針”學習建議
    發表于 03-31 15:53 ?3次下載

    為什么使用指針C++的“指針

    為什么使用指針?因為在操作大型數據和類時,指針可以通過內存地址直接訪問數據,可避免在程序復制大量的代碼,因此指針的效率最高。一般來說,指針
    的頭像 發表于 10-04 10:33 ?5141次閱讀

    C++指針的學習建議

     一。對于眾多人提出的c/c++指針難學的問題做個總結:
    發表于 11-07 17:13 ?8次下載
    <b class='flag-5'>C++</b><b class='flag-5'>指針</b>的學習建議

    C++封裝:this指針

    C++封裝:this指針
    的頭像 發表于 06-29 14:37 ?3476次閱讀
    <b class='flag-5'>C++</b>封裝:this<b class='flag-5'>指針</b>

    【嵌入式技能樹】

    程師嵌入式硬件工程師通用技能樹軟件C/C++語言編程經驗、編程能力、應用開發、OOP面向對象編程方式、軟件框架、C指針、文件IO、進程線程、高級IO、對
    發表于 10-21 10:21 ?16次下載
    【嵌入式技能樹】

    CC++經典著作《C指針

    CC++經典著作《C指針
    發表于 01-17 09:46 ?0次下載

    C++中有函數指針還需要std::function嘛

    C/C++可以使用指針指向一段代碼,這個指針就叫函數指針,假設有這樣一段代碼:
    的頭像 發表于 02-15 14:13 ?510次閱讀
    <b class='flag-5'>C++</b>中有函數<b class='flag-5'>指針</b>還需要std::function嘛

    C++的引用和指針

    之前的文章我們已經介紹了C++的基本類型如int,bool和double等,除了基本類型C++還有一些更復雜的數據類型復合類型,所謂的復合類型就是通過其他類型定義的類型,本篇文章我們將會著重介紹
    的頭像 發表于 03-17 14:00 ?637次閱讀

    C++智能指針的底層實現原理

    C++智能指針的頭文件: #include 1. shared_ptr: 智能指針從本質上來說是一個模板類,用類實現對指針對象的管理。 template class shared_pt
    的頭像 發表于 11-09 14:32 ?748次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>智能指針</b>的底層實現原理
    主站蜘蛛池模板: 成人精品一区二区三区电影| 午夜一级毛片免费视频| 黄色a三级免费看| a天堂资源在线观看| 天天插天天干天天射| 国产小视频在线高清播放| 黄色大片网站| 91视频毛片| 日本三级吹潮| 高清一级做a爱免费视| 四虎影视在线看| 亚洲精品福利你懂| 日本一区二区三区在线网| 69pao强力打造免费高速| 毛片天天看| 在线观看一区二区三区视频| 亚洲人成电影院| 免费人成年激情视频在线观看| 成人亚洲视频| 欧美性猛交xxxx乱大交高清| 99热99热| 国产色窝| 国产在线视频网站| 五月.com| 国产三级播放| 久操伊人| 海棠高h粗暴调教双性男男| 日本黄色美女视频| 淫操| 免费在线视频播放| 五月婷婷婷婷| 国产成人永久免费视频| 美国bj69| 免费黄色在线观看| 国产精品福利久久2020| 一级特黄性生活大片免费观看| 毛片黄| 美女被上视频| 四虎最新地址| 午夜在线| 在线亚洲色图|