最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++11&14-智能指針要點(diǎn)匯總

 更新時(shí)間:2020年06月03日 08:49:40   作者:晟夏的葉  
這篇文章主要介紹了c++11&14-智能指針的要點(diǎn),文中代碼非常詳細(xì),供大家學(xué)習(xí)和參考,感興趣的朋友可以了解下

學(xué)c++的人都知道,在c++里面有一個(gè)痛點(diǎn),就是動(dòng)態(tài)內(nèi)存的管理,就我所經(jīng)歷的一些問(wèn)題來(lái)看,很多莫名其妙的問(wèn)題,最后都發(fā)現(xiàn)是內(nèi)存管理不當(dāng)引起的。

但像java等其他一些語(yǔ)言則不會(huì)有這樣的問(wèn)題,為什么呢,因?yàn)樗鼈冇泻芎玫奶幚韮?nèi)存的方法,比如java的垃圾回收機(jī)制,現(xiàn)在,我們c++終于也有了智能指針。

1. 什么是智能指針

簡(jiǎn)單地說(shuō),智能指針是用對(duì)象去管理一個(gè)資源指針,同時(shí)用一個(gè)計(jì)數(shù)器計(jì)算引用當(dāng)前指針對(duì)象的個(gè)數(shù),當(dāng)管理指針的對(duì)象增加或減少時(shí),計(jì)數(shù)器也相應(yīng)加1或減1,當(dāng)最后一個(gè)指針管理對(duì)象銷毀時(shí),計(jì)數(shù)器為1,此時(shí)在銷毀指針管理對(duì)象的同時(shí),也對(duì)指針管理對(duì)象所管理的指針進(jìn)行delete操作。

下面我們介紹兩個(gè)常用的智能指針std::shared_ptr和std::weak_ptr。

1.1 std::shared_ptr

std::shared_ptr包裝了new操作符動(dòng)態(tài)分配的內(nèi)存,可以自由拷貝復(fù)制,基本上是使用最多的一個(gè)智能指針類型。

下面是一個(gè)代碼例子:

#include <memory>
#include <iostream>
class Test
{
public:
  Test()
  {
    std::cout << "Test()" << std::endl;
  }
  ~Test()
  {
    std::cout << "~Test()" << std::endl;
  }
};
int main()
{
  std::shared_ptr<Test> p1 = std::make_shared<Test>();
  std::cout << "1 ref:" << p1.use_count() << std::endl;
  {
    std::shared_ptr<Test> p2 = p1;
    std::cout << "2 ref:" << p1.use_count() << std::endl;
  }
  std::cout << "3 ref:" << p1.use_count() << std::endl;
  return 0;
}

結(jié)果如下:

Test()
1 ref:1
2 ref:2
3 ref:1
~Test()

針對(duì)代碼解讀如下:

std::make_shared里面調(diào)用了new操作符分配內(nèi)存;
第二個(gè)p1.use_count()之所以顯示為2,是因?yàn)樵黾恿艘脤?duì)象p2,而隨著大括號(hào)的結(jié)束,p2的作用域結(jié)束,所以p1的引用計(jì)數(shù)變回1,而隨著main函數(shù)的結(jié)束,p1的作用域結(jié)束,此時(shí)檢測(cè)到計(jì)數(shù)為1,那就會(huì)在銷毀p1的同時(shí),調(diào)用p1的析構(gòu)函數(shù)delete掉之前分配的內(nèi)存空間;

1.2 std::weak_ptr

std::weak_ptr有什么特點(diǎn)呢?與std::shared_ptr最大的差別是在賦值的時(shí)候,不會(huì)引起智能指針計(jì)數(shù)增加。

weak_ptr被設(shè)計(jì)為與shared_ptr共同工作,可以從一個(gè)shared_ptr或者另一個(gè)weak_ptr對(duì)象構(gòu)造,獲得資源的觀測(cè)權(quán)。但weak_ptr沒(méi)有共享資源,它的構(gòu)造不會(huì)引起指針引用計(jì)數(shù)的增加。同樣,在weak_ptr析構(gòu)時(shí)也不會(huì)導(dǎo)致引用計(jì)數(shù)的減少,它只是一個(gè)靜靜地觀察者。weak_ptr沒(méi)有重載operator*和->,這是特意的,因?yàn)樗还蚕碇羔?,不能操作資源,這是它弱的原因。如要操作資源,則必須使用一個(gè)非常重要的成員函數(shù)lock()從被觀測(cè)的shared_ptr獲得一個(gè)可用的shared_ptr對(duì)象,從而操作資源。

1.2.1 std::shared_ptr相互引用會(huì)有什么后果

代碼如下:

#include <memory>
#include <iostream>
class TestB;
class TestA
{
public:
  TestA()
  {
    std::cout << "TestA()" << std::endl;
  }
  void ReferTestB(std::shared_ptr<TestB> test_ptr)
  {
    m_TestB_Ptr = test_ptr;
  }
  ~TestA()
  {
    std::cout << "~TestA()" << std::endl;
  }
private:
  std::shared_ptr<TestB> m_TestB_Ptr; //TestB的智能指針
}; 
class TestB
{
public:
  TestB()
  {
    std::cout << "TestB()" << std::endl;
  }
  void ReferTestB(std::shared_ptr<TestA> test_ptr)
  {
    m_TestA_Ptr = test_ptr;
  }
  ~TestB()
  {
    std::cout << "~TestB()" << std::endl;
  }
  std::shared_ptr<TestA> m_TestA_Ptr; //TestA的智能指針
};
int main()
{
  std::shared_ptr<TestA> ptr_a = std::make_shared<TestA>();
  std::shared_ptr<TestB> ptr_b = std::make_shared<TestB>();
  ptr_a->ReferTestB(ptr_b);
  ptr_b->ReferTestB(ptr_a);
  return 0;
}

運(yùn)行結(jié)果:

TestA()
TestB()

可以看到,上面代碼中,我們創(chuàng)建了一個(gè)TestA和一個(gè)TestB的對(duì)象,但在整個(gè)main函數(shù)都運(yùn)行完后,都沒(méi)看到兩個(gè)對(duì)象被析構(gòu),這是為什么呢?

原來(lái),智能指針ptr_a中引用了ptr_b,同樣ptr_b中也引用了ptr_a,在main函數(shù)退出前,ptr_a和ptr_b的引用計(jì)數(shù)均為2,退出main函數(shù)后,引用計(jì)數(shù)均變?yōu)?,也就是相互引用。

這等效于說(shuō):

ptr_a對(duì)ptr_b說(shuō),哎,我說(shuō)ptr_b,我現(xiàn)在的條件是,你先釋放我,我才能釋放你,這是天生的,造物者決定的,改不了;
ptr_b也對(duì)ptr_a說(shuō),我的條件也是一樣,你先釋放我,我才能釋放你,怎么辦?
是吧,大家都沒(méi)錯(cuò),相互引用導(dǎo)致的問(wèn)題就是釋放條件的沖突,最終也可能導(dǎo)致內(nèi)存泄漏。

1.2.2 std::weak_ptr如何解決相互引用的問(wèn)題

我們?cè)谏厦娴拇a基礎(chǔ)上使用std::weak_ptr進(jìn)行修改,如下:

#include <iostream>
#include <memory>
class TestB;
class TestA
{
public:
  TestA()
  {
    std::cout << "TestA()" << std::endl;
  }
  void ReferTestB(std::shared_ptr<TestB> test_ptr)
  {
    m_TestB_Ptr = test_ptr;
  }
  void TestWork()
  {
    std::cout << "~TestA::TestWork()" << std::endl;
  }
  ~TestA()
  {
    std::cout << "~TestA()" << std::endl;
  }
private:
  std::weak_ptr<TestB> m_TestB_Ptr;
};
class TestB
{
public:
  TestB()
  {
    std::cout << "TestB()" << std::endl;
  }
  void ReferTestB(std::shared_ptr<TestA> test_ptr)
  {
    m_TestA_Ptr = test_ptr;
  }
  void TestWork()
  {
    std::cout << "~TestB::TestWork()" << std::endl;
  }
  ~TestB()
  {
		////把std::weak_ptr類型轉(zhuǎn)換成std::shared_ptr類型
    std::shared_ptr<TestA> tmp = m_TestA_Ptr.lock();
    tmp->TestWork();
    std::cout << "2 ref a:" << tmp.use_count() << std::endl;
    std::cout << "~TestB()" << std::endl;
  }
  std::weak_ptr<TestA> m_TestA_Ptr;
};
int main()
{
  std::shared_ptr<TestA> ptr_a = std::make_shared<TestA>();
  std::shared_ptr<TestB> ptr_b = std::make_shared<TestB>();
  ptr_a->ReferTestB(ptr_b);
  ptr_b->ReferTestB(ptr_a);
  std::cout << "1 ref a:" << ptr_a.use_count() << std::endl;
  std::cout << "1 ref b:" << ptr_a.use_count() << std::endl;
  return 0;
}

運(yùn)行結(jié)果:

TestA()
TestB()
1 ref a:1
1 ref b:1
~TestA::TestWork()
2 ref a:2
~TestB()
~TestA()

預(yù)覽
由以上代碼運(yùn)行結(jié)果我們可以看到:

所有的對(duì)象最后都能正常釋放,不會(huì)存在上一個(gè)例子中的內(nèi)存沒(méi)有釋放的問(wèn)題;
ptr_aptr_b在main函數(shù)中退出前,引用計(jì)數(shù)均為1,也就是說(shuō),在TestATestB中對(duì)std::weak_ptr的相互引用,不會(huì)導(dǎo)致計(jì)數(shù)的增加。在TestB析構(gòu)函數(shù)中,調(diào)用std::shared_ptr tmp = m_TestA_Ptr.lock(),std::weak_ptr類型轉(zhuǎn)換成std::shared_ptr類型,然后對(duì)TestA對(duì)象進(jìn)行調(diào)用。

1.2.3 std::weak_ptr支持的調(diào)用

weak_ptr<T> w;	//空weak_ptr可以指向類型為T(mén)的對(duì)象
weak_ptr<T> w(shared_ptr sp);	//與sp指向相同對(duì)象的weak_ptr, T必須能轉(zhuǎn)換為sp指向的類型
w = p;	//p可以是shared_ptr或者weak_ptr,賦值后w和p共享對(duì)象
w.reset();	//weak_ptr置為空
w.use_count();	//與w共享對(duì)象的shared_ptr的計(jì)數(shù)
w.expired();	//w.use_count()為0則返回true,否則返回false
w.lock();	//w.expired()為true,返回空的shared_ptr;否則返回指向w的shared_ptr

1.3 std::unique_ptr

uniqut_ptr是一種對(duì)資源具有排他性擁有權(quán)的智能指針,即一個(gè)對(duì)象資源只能同時(shí)被一個(gè)unique_ptr指向。

1.3.1 初始化方式

使用new

T *pT = new T();
std::unique_ptr<T> up1(pT);

通過(guò)make_unique

auto pT = make_unique<T>();

通過(guò)move()函數(shù)

//up也是一個(gè)std::unique_ptr<T>指針
unique_ptr<T> up1 = std::move(up); 

1.3.2 unique_ptr不能被復(fù)制或者拷貝

unique_ptr<T> up(new T()); //ok
unique_ptr<T> up1(up); //error, can not be copy
unique_ptr<T> up2 = up; //error, can not be assigned

1.3.3 unique_ptr可以移動(dòng)賦值或者移動(dòng)拷貝

unique_ptr<T> pT(new T());
unique_ptr<T> pT2 = std::move(pT);	//移動(dòng)賦值,此時(shí)pT被銷毀,為空
unique_ptr<T> pT3(std::move(pt2)); //移動(dòng)拷貝,此時(shí)pT2被銷毀,為空

1.3.4 unique_ptr可以作為函數(shù)的返回值

unique_ptr<T> GetPtr(); //function getthe unique pointer
unique_ptr<T> pT = GetPtr(); // ok

1.3.5 使用范例

#include <iostream>
int main()
{
	std::unique_ptr<int> pInt;
	pInt.reset(new int());
	int *p = pInt.release(); //釋放所有權(quán)
	//由于unique_ptr有std::unique_ptr<T[]>的重載函數(shù),所以它可以用來(lái)管理數(shù)組資源
	std::unique_ptr<int[]> pArray(new int[3]{1,3,3}); 
}

2. 智能指針小結(jié)

可以看出,智能指針其實(shí)是std::shared_ptr和std::unique_ptr, std::shared_ptr可以有多個(gè)引用對(duì)象,但不能互相引用,而std::unique_ptr只能有一個(gè)引用,不能賦值或者拷貝,但可以移動(dòng)賦值和移動(dòng)拷貝,std::weak_ptr實(shí)際上是對(duì)std::shared_ptr的補(bǔ)充,它并不能對(duì)對(duì)象進(jìn)行具體的操作。

注意:shared_ptr,weak_ptr,unique_ptr這些都是模板,并不是指針或者其他的。

以上就是c++11&14-智能指針要點(diǎn)匯總的詳細(xì)內(nèi)容,更多關(guān)于c++11&14 智能指針的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C/C++中的回調(diào)用法詳細(xì)講解

    C/C++中的回調(diào)用法詳細(xì)講解

    這篇文章主要介紹了回調(diào)函數(shù)在C/C++中的重要意義及應(yīng)用,回調(diào)函數(shù)通過(guò)將函數(shù)作為參數(shù)傳遞,實(shí)現(xiàn)了模塊的解耦、靈活性和可擴(kuò)展性,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • C++獲取zip文件列表方法

    C++獲取zip文件列表方法

    本文將介紹獲取zip文件列表的方法,有些新手的朋友可以參考下
    2012-12-12
  • C語(yǔ)言編程入門(mén)之程序頭文件的簡(jiǎn)要解析

    C語(yǔ)言編程入門(mén)之程序頭文件的簡(jiǎn)要解析

    這篇文章主要介紹了C語(yǔ)言編程入門(mén)之程序頭文件的簡(jiǎn)要解析,包括頭文件重復(fù)包含問(wèn)題等方面的說(shuō)明,需要的朋友可以參考下
    2015-12-12
  • c語(yǔ)言printf函數(shù)的使用詳解

    c語(yǔ)言printf函數(shù)的使用詳解

    本篇文章是對(duì)c語(yǔ)言中printf函數(shù)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++ 中構(gòu)造函數(shù)的實(shí)例詳解

    C++ 中構(gòu)造函數(shù)的實(shí)例詳解

    這篇文章主要介紹了C++ 中構(gòu)造函數(shù)的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • C++中的多態(tài)與多重繼承實(shí)現(xiàn)與Java的區(qū)別

    C++中的多態(tài)與多重繼承實(shí)現(xiàn)與Java的區(qū)別

    這篇文章主要介紹了C++中的多態(tài)與多重繼承實(shí)現(xiàn)與Java的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • C++生成格式化的標(biāo)準(zhǔn)字符串實(shí)例代碼

    C++生成格式化的標(biāo)準(zhǔn)字符串實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于C++生成格式化的標(biāo)準(zhǔn)字符串的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • C++超詳細(xì)梳理lambda和function的使用方法

    C++超詳細(xì)梳理lambda和function的使用方法

    C++在C11標(biāo)準(zhǔn)中引入了匿名函數(shù),即沒(méi)有名字的臨時(shí)函數(shù),又稱之為lambda表達(dá)式.lambda表達(dá)式 實(shí)質(zhì)上是創(chuàng)建一個(gè)匿名函數(shù)/對(duì)象,這篇文章主要介紹了lambda和function的使用方法
    2022-08-08
  • linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼

    linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼

    下面小編就為大家?guī)?lái)一篇linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • c++中ref的作用示例解析

    c++中ref的作用示例解析

    這篇文章主要為大家介紹了c++中ref的作用示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04

最新評(píng)論

高州市| 南郑县| 长白| 布尔津县| 沂源县| 太原市| 秦皇岛市| 霍林郭勒市| 竹溪县| 满城县| 德惠市| 固镇县| 津南区| 丹棱县| 竹山县| 山西省| 扶风县| 娱乐| 南丹县| 拉萨市| 巢湖市| 贺州市| 广河县| 本溪市| 广州市| 阿拉善左旗| 通海县| 桐柏县| 瑞丽市| 商洛市| 太保市| 太湖县| 如东县| 丰原市| 拉萨市| 白水县| 乌什县| 栾城县| 嵊泗县| 泾川县| 西林县|