C++內存管理筆記 (二) new與delete表達式

new與delete表達式

我們在申請內存和釋放內存時,一般直接調用C++的new表達式和delete表達式即可,但只會使用,而不知其內部如何運作以及爲何如此運作對於學習者來說並不明智.

new expression

首先,假設我們要創建一個複數對象pc,我們會這樣寫

Complex* pc = new Complex(1,2);

那麼編譯器會如何解析這行代碼呢?

Complex* pc;
try{
	//第一步分配內存,大小爲Complex
	void * mem = operator new(sizeof(Complex)); 
	//第二步強制轉化類型,將申請的空間轉化爲Complex*
	pc = static_cast<Complex*> mem;
	//第三步調用類的構造函數
	pc->Complex::Complex(1, 2);
}
catch(std::bad_alloc){
	//若分配內存失敗就不執行
}

由此可見,編譯器將內存分配和對象構造分開處理.

我們進一步剖析,operator new函數做了什麼.
首先,找到了operator new 聲明在new.cpp中;

void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
  __attribute__((__externally_visible__));
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
  __attribute__((__externally_visible__));
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
  __attribute__((__externally_visible__));
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
  __attribute__((__externally_visible__));

之後找到定義;

operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
  void *p;
  // 如果sz爲0 則令其爲1 ,然後在while循環中調用malloc申請內存
  // 直到 申請成功 或者 拋出異常或者 abort
  /* malloc (0) is unpredictable; avoid it.  */
  if (sz == 0)
    sz = 1;

  while (__builtin_expect ((p = malloc (sz)) == 0, false))
    {
      new_handler handler = std::get_new_handler ();
      if (! handler)
    _GLIBCXX_THROW_OR_ABORT(bad_alloc());
      handler ();
    }

  return p;
}

至此,脈絡清晰,總結一下就是:調用new表達式,new內部會調用C++函數operator new,在operrator new中,進一步調用malloc.
放一張侯捷大神的圖
在這裏插入圖片描述

delete expression

有了new的基礎,這裏就放一張大神的圖.
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章