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

C++中的new/delete、構造/析構函數(shù)、dynamic_cast分析

 更新時間:2019年05月24日 10:47:11   作者:子宇24  
這篇文章主要介紹了C++中的new/delete、構造/析構函數(shù)、dynamic_cast分析 本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下

1,new 關鍵字和 malloc 函數(shù)區(qū)別(自己、功能、應用):

    1,new 關鍵字是 C++ 的一部分:

       1,如果是 C++ 編譯器,則肯定可以用 new 申請堆空間內存;

    2,malloc 是由 C 庫提供的函數(shù):

       1,如果沒有相應的庫,malloc 將不能使用;

       2,有些特殊的嵌入式開發(fā)中,少了 C 庫,則就不能動態(tài)內存分配;

    3,new 以具體類型為單位進行內存分配;

       1,面向對象中一般用 new,不用 malloc;

    4,malloc 以字節(jié)為單位進行內存分配;

    5,new 在申請內存空間時可進行初始化;

       1,觸發(fā)構造函數(shù)調用;

    6,malloc 僅根據(jù)需要申請定量的內存空間;

       1,對象的創(chuàng)建只能用 new,malloc 不適合面向對象開發(fā);

2,下面代碼輸出什么?為什么?見 new 和 malloc 的區(qū)別編程實驗:

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Test
{
  int* mp; //為了說明 free() 可能造成內存泄漏問題而添加的成員變量;
public:
  Test()
  {
    cout << "Test::Test()" << endl;
    mp = new int(100); // 申請 4 個字節(jié)堆空間并初始化為 100;
    cout << *mp << endl;
  }
  ~Test()
  {
    delete mp; // 析構函數(shù)歸還堆空間;但是如果僅僅用 free() 函數(shù)歸還堆空間,這里析構函數(shù)沒有調用,則對象沒有摧毀,那么就造成了堆空間泄漏,這在大型項目開發(fā)中是不可原諒的;
    cout << "~Test::Test()" << endl;
  }
};
int main()
{
  Test* pn = new Test; // 第一步申請堆空間,第二步(申請成功后)在堆空間上調用構造函數(shù)、因為需要初始化;
  Test* pm = (Test*)malloc(sizeof(Test)); // 這行代碼運行完后,pm 并沒有指向合法的對象,它僅僅指向一片內存空間而已,這個時候這片內存空間不能夠成為一片合法的對象,因為就沒有對象;
  delete pn; // 動態(tài)歸還堆空間;第一步 delete 觸發(fā)析構函數(shù)調用,摧毀對象,第二步歸還堆空間;在歸還堆空間的時候,要先摧毀掉對象,否則容易出現(xiàn)內存泄漏;
  free(pm); // 動態(tài)規(guī)劃堆空間;僅歸還堆空間,不觸發(fā)析構函數(shù)調用;這里不能用 delete pm,因為這樣會對非法對象調用構造函數(shù),而對于析構函數(shù)中的 delete mp 來說,這樣的影響是深遠的,不知道什么時候就會帶來 bug,且不可調試,只能通過“代碼走查”的方式來檢查是不是混用了兩種類型的申請釋放堆空間函數(shù);
  return 0;
}

1,結論:

       1,free() 可以釋放由 new 申請來的堆空間,但是 free() 不會進行析構函數(shù)的調用,因此有可能造成內存泄漏;

       2,new 和 delete,malloc 和 free 只能匹配使用,不能混用;

3,new 和 malloc 的區(qū)別(自己、功能、應用):

    1,new 在所有 C++ 編譯器中都被支持;

    2,malloc 在某些系統(tǒng)開發(fā)中是不能調用的;

    3,new 能夠觸發(fā)構造函數(shù)的調用;

    4,malloc 僅分配需要的內存空間;

    5,對象的創(chuàng)建只能使用 new;

    6,malloc 不適合面向對象開發(fā);

4,下面的代碼輸出什么?為什么?

    1,代碼示例:

int main()
{
  Test* pn = new Test; // 調用構造函數(shù);
  test* pm = (Test*)malloc(sizeof(Test)); // 僅申請堆空間;
  delete pn; // 調用析構函數(shù);
  free(pm); // 僅釋放堆空間;
   return 0;
}

5,delete 和 free 的區(qū)別(自己、功能、應用):

    1,delete 在所有 C++ 編譯器中都被支持;

    2,free 在某些系統(tǒng)開發(fā)中是不能調用;

    3,delete 能夠觸發(fā)析構函數(shù)的調用;

    4,free 僅歸還之前分配的內存空間;

    5,對象的銷毀只能使用 delete;

    6,free 不適合面向對象開發(fā)。

6,構造函數(shù)是否可以成為虛函數(shù)?析構函數(shù)是否可以成為虛函數(shù)?

7,構造函數(shù)不可能成為虛函數(shù):

    1,在構造函數(shù)執(zhí)行結束后,虛函數(shù)表指針才會被正確的初始化;

       1,C++ 里面的多態(tài)是通過虛函數(shù)表和指向虛函數(shù)表指針完成的,虛函數(shù)表指針是由編譯器創(chuàng)建的,同時也是由編譯器進行初始化,在構造函數(shù)執(zhí)行結束之后,虛函數(shù)表的指針才會被正確進行初始化;

       2,在構造函數(shù)執(zhí)行的過程當中,虛函數(shù)表的指針有可能是沒有被正確初始化的,因為對于虛函數(shù)表和虛函數(shù)表指針的實現(xiàn),對于不同的 C++ 編譯器而言,實現(xiàn)有可能不一樣,但是所有的 C++ 編譯器都會保證在構造函數(shù)執(zhí)行結束后,虛函數(shù)表指針肯定會被正確的初始化,在這之前,是沒有保證的;

       3,所以構造函數(shù)不可能成為虛函數(shù),創(chuàng)建一個對象的時候,我們需要構造函數(shù)來初始化虛函數(shù)表的指針,因此構造函數(shù)相當于一個入口點,這個入口點負責虛函數(shù)調用的前期工作,這個入口點當然不可能是虛函數(shù);

8,析構函數(shù)可以成為虛函數(shù):

    1,析構函數(shù)在對象銷毀之前被調用,對象銷毀之前意味著虛函數(shù)指針是正確的指向對應的虛函數(shù)表的;

    2,建議在設計類時將析構函數(shù)聲明為虛函數(shù)(工程中設計一個父類的析構函數(shù)為虛函數(shù));

       1,賦值兼容性申請子類對象給父類指針時,當 delete 作用在指針上時,編譯器會直接根據(jù)指針類型(此時是父類)來調用相應的析構函數(shù),若父類加上 virtual,編譯器可以根據(jù)指針指向的實際對象(此時是子類)決定如何調用析構函數(shù)(多態(tài));

9,構造、析構、虛函數(shù)編程實驗:

#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
  Base() // 若申請為析構函數(shù),則編譯器在此處顯示:error:constructors cannot be declared virtual.
  {
    cout << "Base()" << endl;
  }
  virtual void func() 
  {
    cout << "Base::func()" << endl;
  }
  virtual ~Base() // 申請為虛函數(shù)時,編譯器無顯示
  {  
    cout << "~Base()" << endl;
  }
};
class Derived : public Base
{
public:
  Derived()
  {
    cout << "Derived()" << endl;
  }
  virtual void func()
  {
    cout << "Derived::func()" << endl;
  }
  ~Derived()
  { 
    cout << "~Derived()" << endl;
  }
};
int main()
{
  Base* p = new Derived();
  // ...
  delete p; // 期望調用完子類析構函數(shù)再調用父類的析構函數(shù);但是如果父類沒有申請為析構函數(shù),則只調用父類析構函數(shù);這是因為此時刪除的是一個父類的指針,由于并沒有將析構函數(shù)申請為 virtual,因此在這樣情況下,編譯器直接根據(jù)指針 p 的類型來決定調用哪一個構造函數(shù),由于指針 p 的類型是父類的類型,所以編譯器直接暴力認為調用父類構造函數(shù)就可以了;當將父類的虛函數(shù)聲明為 virtual 時,編譯器就不會簡單的根據(jù)指針 p 的類型來簡單調用父類的或者是子類的析構函數(shù)了,這個時候由于析構函數(shù)是虛函數(shù),所以在執(zhí)行這行代碼的時候,編譯器會根據(jù)指針 p 指向的實際對象來決定如何調用析構函數(shù),這是多態(tài);
  return 0;
}

1,工程中設計一個類作為父類出現(xiàn)時,我們都要將析構函數(shù)聲明為虛函數(shù),否 則就有可能產生內存泄漏,因為有可能跳過子類析構函數(shù)的調用,如果子類     析構函數(shù)中有釋放資源的操作(動態(tài)內存空間),則后果不堪設想;

10,構造函數(shù)中是否可以發(fā)生多態(tài)?析構函數(shù)中是否可以發(fā)生多態(tài)?

11,構造函數(shù)中(構造函數(shù)中調用虛函數(shù))不可能發(fā)生多態(tài)行為:

    1,在構造函數(shù)執(zhí)行時,虛函數(shù)表指針未被正確初始化;

12,析構函數(shù)中(析構函數(shù)中調用虛函數(shù))不可能發(fā)生多態(tài)行為:

    1,在析構函數(shù)執(zhí)行時,虛函數(shù)表指針可能已經被摧毀;

13,析構函數(shù)和構造函數(shù)中(調用虛函數(shù)時)不能發(fā)生多態(tài)行為,只調用當前類中的函數(shù)版本;

    1,構造函數(shù)和析構函數(shù)中調用虛函數(shù)實驗:

#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
  Base()
  {
    cout << "Base()" << endl;
    func();
  }
  virtual void func() 
  {
    cout << "Base::func()" << endl;
  }
  virtual ~Base()
  {
    func();
    cout << "~Base()" << endl;
  }
};
class Derived : public Base
{
public:
  Derived()
  {
    cout << "Derived()" << endl;
    func();
  }
  virtual void func()
  {
    cout << "Derived::func()" << endl;
  }
  ~Derived()
  {
    func();
    cout << "~Derived()" << endl;
  }
};
int main()
{
  Base* p = new Derived(); // 打印 Base(),Base::func(),Derived(),Derived::func(),                
  // ...
  delete p; // 打印 Derived::func(),~Derived(),Base::func(), ~Base();
  return 0;
}

14,繼承中如何正確的使用強制類型轉換?

    1,dynamic_cast 是與繼承相關的類型轉換關鍵字;

    2,dynamic_cast 要求相關的類中必須有虛函數(shù);

    3,用于有直接或者間接繼承關系的指針(引用)之間;

       1,指針:

           1,轉換成功:得到目標類型的指針;

           2,轉換失?。旱玫揭粋€空指針;

       2,引用:

           1,轉換成功:得到目標類型的引用;

           2,轉換失?。旱玫揭粋€異常操作信息;

    4,編譯器會檢查 dynamic_cast 的使用是否正確;

       1,在 C++ 編譯器中得到足夠重視,是非常有地位的一個類型轉換關鍵字;

       2,使用不正確編譯器會報錯;

    5,類型轉換的結果只可能在運行階段才能得到;

       1,動態(tài)的類型轉換,轉換結果運行階段才能得到;

15,dynamic_cast 的使用編程實驗:

#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
  Base()
  {
    cout << "Base::Base()" << endl;
  }
  virtual ~Base() // 工程經驗;
  {
    cout << "Base::~Base()" << endl;
  }
};
class Derived : public Base
{
};
int main()
{
/* 
    Base* p = new Derived;
  Derived* pd = p; // 編譯器顯示:error:invalid conversion from 'Base*' to 'Derived*';
           // 未有虛函數(shù)時,用 dynamic_cast 轉換,編譯器顯示:error: cannot dynamic_cast 'p' (of type 'class Base*') to type 'Derived*' (source type is not polymorphic(多態(tài)的))
           // 有虛函數(shù)且用了 dynamic_cast 也要判斷 pd 不為空;
*/
  Base* p = new Base;
  Derived* pd = dynamic_cast<Derived*>(p); // 不合法,不能使用子類指針,指向父類對象;編譯器編譯階不報錯;但是運行時 pd = 0; 意味著此處強制類型轉換不成功;
  if( pd != NULL ) // 這樣的判斷很有必要;
  {
    cout << "pd = " << pd << endl;
  }
  else
  {
    cout << "Cast error!" << endl;
  }
  delete p;
  return 0;
}

總結

以上所述是小編給大家介紹的C++中的new/delete、構造/析構函數(shù)、dynamic_cast分析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

相關文章

  • 詳解c++ atomic原子編程中的Memory Order

    詳解c++ atomic原子編程中的Memory Order

    在多核編程中,我們使用內核對象【如:事件對象(Event)、互斥量對象(Mutex,或互斥體對象)、信號量對象(Semaphore)等】來避免多個線程修改同一個數(shù)據(jù)時產生的競爭條件。本文將詳細介紹c++ atomic原子編程中的Memory Order。
    2021-06-06
  • C++計算圓形、矩形和三角形的面積

    C++計算圓形、矩形和三角形的面積

    這篇文章介紹了C++計算圓形、矩形和三角形面積的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • C++實現(xiàn)猜數(shù)游戲

    C++實現(xiàn)猜數(shù)游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)猜數(shù)游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C語言實現(xiàn)數(shù)組棧的代碼示例

    C語言實現(xiàn)數(shù)組棧的代碼示例

    棧是一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作,進行數(shù)據(jù)插入和刪除操作的一端稱為棧頂,另一端稱為棧底,本文給大家介紹了C語言實現(xiàn)數(shù)組棧的代碼示例,需要的朋友可以參考下
    2024-07-07
  • bloom filter概念講解以及代碼分析

    bloom filter概念講解以及代碼分析

    Bloom filter 優(yōu)點就是它的插入和查詢時間都是常數(shù),另外它查詢元素卻不保存元素本身,具有良好的安全性
    2013-09-09
  • linux系統(tǒng)中c++寫日志文件功能分享

    linux系統(tǒng)中c++寫日志文件功能分享

    這篇文章主要介紹了linux系統(tǒng)中c++寫日志文件功能,簡化了glog,只保留了寫日志文件的功能,只是改寫了linux版本,需要的朋友可以參考下
    2014-03-03
  • C語言指針詳解

    C語言指針詳解

    這篇文章非常詳細的講解了C語言中指針的概念,包含多種方法,多種定義,全面的說明了C語言的特性
    2021-06-06
  • 一篇文章詳解Qt中如何訪問數(shù)據(jù)庫

    一篇文章詳解Qt中如何訪問數(shù)據(jù)庫

    Qt是一個廣泛使用的跨平臺應用程序框架,它提供了許多功能,包括數(shù)據(jù)庫訪問,這篇文章主要給大家介紹了關于Qt中如何訪問數(shù)據(jù)庫的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • C++回溯算法廣度優(yōu)先搜索舉例分析

    C++回溯算法廣度優(yōu)先搜索舉例分析

    回溯在迷宮搜索中使用很常見,就是這條路走不通,然后返回前一個路口,繼續(xù)下一條路。回溯算法說白了就是窮舉法,下面讓我們一起來看看吧
    2022-03-03
  • VC程序設計小技巧20例

    VC程序設計小技巧20例

    這篇文章主要介紹了VC程序設計小技巧20例,需要的朋友可以參考下
    2014-07-07

最新評論

马鞍山市| 双峰县| 张北县| 石棉县| 临颍县| 田东县| 汤阴县| 静乐县| 中山市| 同德县| 瓮安县| 永州市| 德安县| 昂仁县| 英吉沙县| 邯郸县| 广东省| 万山特区| 城口县| 武川县| 曲靖市| 城固县| 呈贡县| 定兴县| 新野县| 凌云县| 玛曲县| 钦州市| 尤溪县| 尉氏县| 剑河县| 宜阳县| 稷山县| 濉溪县| 大邑县| 汝阳县| 石首市| 宁远县| 安塞县| 从江县| 罗定市|