注
由于項(xiàng)目需求需要使用c++, 特意寫點(diǎn)學(xué)習(xí)筆記, 以下例子均來自網(wǎng)友分享的
資料, 如果原作者覺得有損您的利益, 請(qǐng)通知本人進(jìn)行刪除.
make_shared & shared_ptr
typedef struct _StructA StructA;
typedef struct _StructB StructB;
struct _StructA
{
int i;
std::shared_ptr<StructB> pStructB;
_StructA(): i(int())
{
printf("_StructA alloc \n");
};
~_StructA()
{
printf("_StructA dealloc \n");
};
} ;
struct _StructB
{
int i;
std::shared_ptr<StructA> pStructA;
_StructB(): i(int())
{
printf("_StructB alloc \n");
};
~_StructB()
{
printf("_StructB dealloc \n");
};
};
- make_shared 和 shared_ptr 的用處
// make_shared 和 shared_ptr 設(shè)計(jì)初衷是引入引用計(jì)數(shù)這個(gè)概念來減少程序
// 員的工作量. 他的設(shè)計(jì)想法跟 Objective-c 的引用計(jì)數(shù)有點(diǎn)類似。請(qǐng)看以下代碼:
int main(int argc, const char * argv[])
{
printf("----- start ----- \n");
std::shared_ptr<StructA> pA = std::make_shared<StructA>();
std::shared_ptr<StructB> pB (new StructB());
printf("----- end ----- \n");
return 0;
}
// 打印結(jié)果
**----- start ----- **
**_StructA alloc **
**_StructB alloc **
**----- end ----- **
**_StructB dealloc **
**_StructA dealloc **
通過實(shí)驗(yàn)可以看出, 超出作用域之后就會(huì)對(duì) shared_ptr 所作用的對(duì)象進(jìn)行引用計(jì)數(shù)減少1, 如果發(fā)現(xiàn) shared_ptr 所作用的對(duì)象引用計(jì)數(shù)為0則說明笋粟,這個(gè)對(duì)象需要釋放內(nèi)存.
- 環(huán)形引用
printf("----- start ----- \n");
std::shared_ptr<StructA> pA = std::make_shared<StructA>();
std::shared_ptr<StructB> pB = std::make_shared<StructB>();
pA->pStructB = pB;
pB->pStructA = pA;
printf("----- end ----- \n");
// 打印結(jié)果
**----- start ----- **
**_StructA alloc **
**_StructB alloc **
**----- end ----- **
環(huán)形應(yīng)用: 就是對(duì)象 A 持有對(duì)象 B 的強(qiáng)引用, 對(duì)象 B 持有對(duì)象 A 的強(qiáng)應(yīng)用,最終導(dǎo)致 A 和 B 都無法釋放怀挠。
// 解決方法, 其中一方使用弱引用
struct _StructB
{
int i;
// 改為弱引用, 同理針對(duì) StructA 也可以這樣做
std::weak_ptr<StructA> pStructA;
// std::shared_ptr<StructA> pStructA;
_StructB(): i(int())
{
printf("_StructB alloc \n");
};
~_StructB()
{
printf("_StructB dealloc \n");
};
};
- make_shared 和 shared_ptr 區(qū)別
/**
* 1. 執(zhí)行申請(qǐng) 數(shù)據(jù)體(StructA) 的內(nèi)存申請(qǐng)
* 2. 執(zhí)行控制塊的內(nèi)存申請(qǐng)
*/
std::shared_ptr<StructA> pA1(new StructA());
/**
* 數(shù)據(jù)體 和 控制塊的 內(nèi)存一塊申請(qǐng)
*/
std::shared_ptr<StructA> pA2 = std::make_shared<StructA>();
- make_shared 和 shared_ptr 如何選擇
void fun(std::shared_ptr<StructA> pA, std::shared_ptr<StructB> pB)
{
printf("pA->i = %d pB->i = %d \n", pA->i, pB->i);
}
int main(int argc, const char * argv[])
{
/**
* 因?yàn)镃++允許參數(shù)在計(jì)算的時(shí)候打亂順序,因此可能出現(xiàn)以下順序
* 1. new StructA
* 2. new StructB // 如果在此步出現(xiàn)問題, 那么就會(huì)導(dǎo)致 1. 所產(chǎn)生的內(nèi)存無人管理, 造成內(nèi)存泄露
* 3. shared_ptr A
* 4. shared_ptr B
*/
fun(std::shared_ptr<StructA>(new StructA()), std::shared_ptr<StructB>(new StructB()));
return 0;
}
// 解決方法1
auto pSA = std::shared_ptr<StructA>(new StructA());
auto pSB = std::shared_ptr<StructB>(new StructB());
fun(pSA, pSB);
// 解決方法2
fun(std::make_shared<StructA>(), std::make_shared<StructB>());
. weak_ptr
- weak_ptr 主要是用來判斷 shared_ptr 所指向的數(shù)據(jù)內(nèi)存是否存在, 因?yàn)閙ake_shared 只作一次內(nèi)存分配, shared_ptr 可以把這種內(nèi)存分配分為兩個(gè)步驟, weak_ptr 可以通過 lock 來判斷 shared_ptr 所指向的數(shù)據(jù)內(nèi)存是否被釋放
std::shared_ptr<StructA> pSA(new StructA());
std::weak_ptr<StructA> wPSA = pSA;
pSA.reset(new StructA());
auto p = wPSA.lock();
std::cout<< p << std::endl;
std::cout<< wPSA.use_count() << std::endl;
// 打印結(jié)果
**_StructA alloc **
**_StructA alloc **
**_StructA dealloc **
**0x0**
**0**
**_StructA dealloc **
- weak_ptr 使用注意
// 主線程
std::shared_ptr<StructA> pSA(new StructA());
std::weak_ptr<StructA> wPSA(pSA);
// 子線程 1
pSA.reset(new StructA());
// 子線程 2
// 錯(cuò)誤做法, 現(xiàn)在編譯器好像也不允許這么做
// StructA *p = wPSA.get();
// if ( p )
// {
// p->i = 5;
// }
// 正確做法
if ( auto p = wPSA.lock() )
{
p->i = 5;
}