欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

C++淺拷貝與深拷貝及引用計(jì)數(shù)分析

C++淺拷貝與深拷貝及引用計(jì)數(shù)分析

梅州網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,梅州網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為梅州成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的梅州做網(wǎng)站的公司定做!

在C++開發(fā)中,經(jīng)常遇到的一個(gè)問題就是與指針相關(guān)的內(nèi)存管理問題,稍有不慎,就會(huì)造成內(nèi)存泄露、內(nèi)存破壞等嚴(yán)重的問題。不像Java一樣,沒有指針這個(gè)概念,所以也就不必?fù)?dān)心與指針相關(guān)的一系列問題,但C++不同,從C語言沿襲下來的指針是其一大特點(diǎn),我們常常要使用new/delete來動(dòng)態(tài)管理內(nèi)存,那么問題來了,特別是伴隨著C++的繼承機(jī)制,如野指針、無效指針使用、內(nèi)存泄露、double free、堆碎片等等,這些問題就像地雷一樣,一不小心就會(huì)踩那么幾顆。

先來談一下C++類中常見的淺拷貝問題,以及由此引發(fā)的double free。什么是淺拷貝?當(dāng)類中的成員變量包括指針時(shí),而又沒有定義自己的拷貝構(gòu)造函數(shù),那么在拷貝一個(gè)對(duì)象的情況下,就會(huì)調(diào)用其默認(rèn)拷貝構(gòu)造函數(shù),其實(shí)這個(gè)函數(shù)沒做什么事,只是對(duì)其成員變量作了個(gè)簡(jiǎn)單的拷貝,也就是所謂的位拷貝,它們指向的還是同一個(gè)存儲(chǔ)空間,當(dāng)對(duì)象析構(gòu)時(shí),就會(huì)析構(gòu)多次,也就是double free,下面舉例說明。

class Common
{
public:
  Common()
  {
    std::cout << "Common::Common" << std::endl;
  }

  Common(const Common &r)
  {
    std::cout << "Common::Common copy-constructor" << std::endl;
  }

  ~Common()
  {
    std::cout << "Common::~Common" << std::endl;
  }
};

類Common是個(gè)一般的類,定義了構(gòu)造、拷貝構(gòu)造和析構(gòu)函數(shù),在函數(shù)里輸出一些log,用以跟蹤函數(shù)調(diào)用情況。

class BitCopy
{
public:
  BitCopy()
    : m_p(new Common)
  {
    std::cout << "BitCopy::BitCopy" << std::endl;
  }

  ~BitCopy()
  {
    std::cout << "BitCopy::~BitCopy" << std::endl;
    if (m_p) {
      delete m_p;
      m_p = NULL;
    }
  }

private:
  Common *m_p;
};

類BitCopy就是一個(gè)淺拷貝類,成員變量是我們剛定義的類指針,構(gòu)造函數(shù)實(shí)例化成員變量,析構(gòu)函數(shù)delete成員變量,沒有定義拷貝構(gòu)造函數(shù)。

int main()
{
  BitCopy a;
  BitCopy b(a);
  return 0;
}
log如下:
Common::Common
BitCopy::BitCopy
BitCopy::~BitCopy
Common::~Common
BitCopy::~BitCopy
Common::~Common
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001f4e010 ***
已放棄 (核心已轉(zhuǎn)儲(chǔ))

從上面的log可以看出,對(duì)象a調(diào)用了構(gòu)造函數(shù),對(duì)象b調(diào)用的是默認(rèn)拷貝構(gòu)造函數(shù),最后析構(gòu)了兩次,從而造成double free,核心已轉(zhuǎn)儲(chǔ)即core dump。

針對(duì)以上問題,該怎么解決呢?有兩個(gè)辦法,一個(gè)是深拷貝,一個(gè)是引用計(jì)數(shù)。先來看一下深拷貝,深拷貝要定義自己的拷貝構(gòu)造函數(shù),在函數(shù)中給成員變量重新分配存儲(chǔ)空間,也就是所謂的值拷貝,這樣它們所指向的就是不同的存儲(chǔ)空間,析構(gòu)時(shí)不會(huì)有問題,但這種方法只適用于較小的數(shù)據(jù)結(jié)構(gòu),如果數(shù)據(jù)結(jié)構(gòu)過大,多次分配存儲(chǔ)空間之后,剩余的存儲(chǔ)空間將逐漸減小,

下面看個(gè)例子。

class ValueCopy
{
public:
  ValueCopy()
    : m_p(new Common)
  {
    std::cout << "ValueCopy::ValueCopy" << std::endl;
  }

  ValueCopy(const ValueCopy &r)
    : m_p(new Common(*r.m_p))
  {
    std::cout << "ValueCopy::ValueCopy copy-constructor" << std::endl;
  }

  ~ValueCopy()
  {
    std::cout << "ValueCopy::~ValueCopy" << std::endl;
    if (m_p) {
      delete m_p;
      m_p = NULL;
    }
  }

private:
  Common *m_p;
};

類ValueCopy是個(gè)深拷貝類,與上面例子的淺拷貝類不同的是定義了拷貝構(gòu)造函數(shù),在函數(shù)中給成員變量重新分配存儲(chǔ)空間,下面是用法及l(fā)og。

int main()
{
  ValueCopy c;
  ValueCopy d(c);
  return 0;
}
Common::Common
ValueCopy::ValueCopy
Common::Common copy-constructor
ValueCopy::ValueCopy copy-constructor
ValueCopy::~ValueCopy
Common::~Common
ValueCopy::~ValueCopy
Common::~Common

從上面的log可以看出,對(duì)象c調(diào)用了構(gòu)造函數(shù),對(duì)象d調(diào)用的是自定義拷貝構(gòu)造函數(shù),最后析構(gòu)了兩次而沒有問題,可見深拷貝的用處所在。

引用計(jì)數(shù)與深拷貝不同,方法是共享同一塊存儲(chǔ)空間,這個(gè)對(duì)大的數(shù)據(jù)結(jié)構(gòu)比較有利。使用引用計(jì)數(shù),需要在類中定義一個(gè)成員變量專門用于計(jì)數(shù),初始值為1,后面引用了這個(gè)對(duì)象就加1,對(duì)象銷毀時(shí)引用減1,但并不真正的delete這個(gè)對(duì)象,只有當(dāng)這個(gè)成員變量的值為0時(shí)才進(jìn)行delete,例子如下。

class A
{
public:
  A()
    : m_refCount(1)
  {
    std::cout << "A::A" << std::endl;
  }

  A(const A &r)
    : m_refCount(1)
  {
    std::cout << "A::A copy-constructor" << std::endl;
  }

  ~A()
  {
    std::cout << "A::~A" << std::endl;
  }

  void attach()
  {
    std::cout << "A::attach" << std::endl;
    ++m_refCount;
  }

  void detach()
  {
    if (m_refCount != 0) {
      std::cout << "A::detach " << m_refCount << std::endl;
      if (--m_refCount == 0) {
        delete this;
      }
    }
  }

private:
  int m_refCount;
};

class B
{
public:
  B()
    : m_pA(new A)
  {
    std::cout << "B::B" << std::endl;
  }

  B(const B &r)
    : m_pA(r.m_pA)
  {
    std::cout << "B::B copy-constructor" << std::endl;
    m_pA->attach();
  }

  ~B()
  {
    std::cout << "B::~B" << std::endl;
    m_pA->detach();
  }

private:
  A* m_pA;
};

類A用到了引用計(jì)數(shù),構(gòu)造和拷貝構(gòu)造函數(shù)都初始化為1,attach()函數(shù)為引用加1,detach()函數(shù)為引用減1,當(dāng)引用計(jì)數(shù)值為0時(shí)delete對(duì)象。類B中的成員變量有個(gè)指針指向A,拷貝構(gòu)造函數(shù)中調(diào)用了attach(),析構(gòu)函數(shù)中調(diào)用了detach(),這樣也是一種保護(hù),不會(huì)有內(nèi)存泄露,也不會(huì)有double free,log如下。

int main()
{
  B e;
  B f(e);
  return 0;
}
A::A
B::B
B::B copy-constructor
A::attach
B::~B
A::detach 2
B::~B
A::detach 1
A::~A

從log中可以看出,指針成員變量的引用計(jì)數(shù)為2,這是正確的,最后正確delete,沒有問題。

在類中只要有指針成員變量,就要注意以上問題,另外,operator=這個(gè)賦值操作符也要在適當(dāng)?shù)臅r(shí)候進(jìn)行重載。有時(shí)候,如果想規(guī)避以上問題,可以聲明拷貝構(gòu)造函數(shù)和operator=操作符為private而不去實(shí)現(xiàn)它們。

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

網(wǎng)頁題目:C++淺拷貝與深拷貝及引用計(jì)數(shù)分析
當(dāng)前地址:http://aaarwkj.com/article18/jegpdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、網(wǎng)站改版、網(wǎng)站營(yíng)銷、面包屑導(dǎo)航、網(wǎng)站設(shè)計(jì)公司、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名
日韩人妻高清精品专区| 亚洲综合激情一区二区| 99国产综合精品女| 黄色午夜福利在线观看| 欧美日韩国产精品一区二区三区| 欧美色一区二区三区四区| 成人国产精品2021| 国产精品国产亚洲av| 香蕉视频欧美久久精品| 国产内射一级一片高清视频观看| 日韩免费色视频一区| 国产精品精品久久久久久| 日本大胆高清人体艺术| 精品少妇人妻一区二区三区| 久草国产免费福利在线视频| 国产精品又大又黑又长又粗| 色婷婷亚洲综合色一区二区| 亚洲激情一区在线观看| av天堂午夜精品蜜臀| 国产精品国产亚洲精品| 国产又粗又猛又爽黄老大爷 | 亚洲av成人三区国产精品| 中文字幕日韩人妻av| 欧美日韩69av网| 欧美aⅴ精品一区二区三区| 91青青草原免费观看| 怡红院怡春院视频免费看| 欧美日韩精品亚洲成人精品| 国产精品国产三级区| 欧美中文字幕精在线不卡| 91老熟女露脸大合集| 国产剧情av在线播放| 激情欧美精品桃桃激情| 四虎在线观看免费资源| 亚洲禁看av一区不卡| 欧美黄片在线播放视频| 99精品国产中文字幕| 亚洲成年人黄片在线播放| 日本美女阴部毛茸茸视频| 色婷婷国产精品久久包臀| 麻豆视频国产一区二区|