過載operator new 函式
過載operator new 函式
取消析構函式的注釋
從上到下越接近作業系統
分配釋放
類屬可否過載
malloc()
free()
c函式不可
newdelete
c++表示式
不可::operator new()
::operator delete()
c++ 函式
可allocator::allocate()
allocator::deallocate()
c++標準庫
可自由設計來搭配容器使用
當呼叫 new的時候 事實上呼叫的時 ::operator new()
比如 int* pi = new int;
編譯器事實上會執行時的時 pi = static_cast(::operator new(sizeof(int)));
這裡的 operator new 是個全域性函式,可以被過載,如果不去過載它,則編譯器會呼叫預設的operator new 函式
operator new 的函式定義邏輯如下:
void* operator new(size_t size, const std::nothrow_t&) _throw0()
return(p);
}
如果malloc 成功,則p != 0 return p, 返回成功分配的位址
如果malloc 不成功, 則 p==0 調函式_callnewh函式,
正常情況下的new表示式
#include using namespace std;
int main(void)
catch (std::bad_alloc& e) }
cout << "done" << endl;
#if defined(_win32)
system("pause");
#endif // defined(_win32)
return 0;
}
執行結果:
分析: 因為不斷的呼叫了new, 也就是::operator new, 最終導致堆空間不足,所以最終丟擲了std::bad_alloc異常。
設定new_handler但不拋異常
#include using namespace std;
void new_handler()
int main(void)
catch (std::bad_alloc& e)
} cout << "done" << endl;
#if defined(_win32)
system("pause");
#endif // defined(_win32)
return 0;
}
執行結果
分析:當記憶體不夠用時,_callnewh呼叫了 註冊過的 ::new_handler,所以_callnewh返回值為1,但::new_handler 並沒有做什麼記憶體釋放的工作,沒有產生空閒的堆空間,但卻不丟擲異常,此時::operator new 就陷入了死迴圈,註冊過的::new_handler會一直被呼叫。 ps new_handler的作用時為了在記憶體不夠時,在這個函式中清理一些記憶體來**新開闢的需求。
設定new_handler 並丟擲異常
#include using namespace std;
void new_handler()
int main(void)
catch (std::bad_alloc& e)
} cout << "done" << endl;
#if defined(_win32)
system("pause");
#endif // defined(_win32)
return 0;
}
執行結果:
分析:嗯,, 這個應該很好理解。
如果想不拋異常呢
int *p = new(std::nothrow)[size];
這樣 如果 分配不到記憶體,則返回乙個null(0), 克通過p 是否 為 null 來判斷是否分配成功。
#include using namespace std;
inline void * operator new(size_t size)
int main(void)
catch (std::bad_alloc& e)
} cout << "done" << endl;
#if defined(_win32)
system("pause");
#endif // defined(_win32)
return 0;
}
執行結果
分析:當 呼叫 new 時呼叫了 過載的 void* operator new (size_t size); 方法,當malloc 不能再分配時p == null,丟擲std::bad_alloc 異常。
#include using namespace std;
inline void * operator new(size_t size)
inline void* operator new(size_t size)
struct complex
//~complex()
};int main(void)
catch (std::bad_alloc& e)
cout << "done" << endl;
#if defined(_win32)
system("pause");
#endif // defined(_win32)
return 0;
}
執行結果
分析這裡的new ( p) int(4) 這種形式叫做placement new, 是通過乙個指標呼叫建構函式, new§ 事實上的函式形式是 operator new(size_t, void* ) 也可以被過載,編譯器預設的處理方式就是 返回 指標本身。
這裡過載了operator new 函式,所以在使用 new 時就不去呼叫 operator new函式而是呼叫 operator new 函式。這裡一共new 了 2 個complex 物件,乙個complex 由2個double 組成(16個位元組), 2個一共32個位元組。這裡我故意注釋掉了析構函式,因為如果乙個物件有析構函式,那麼在開闢物件陣列時還需要再多開闢size_t個位元組(x86: 4個位元組, x64: 8個位元組),以確保能正確的儲存物件的個數,以正確的對每個物件呼叫析構函式。
#include using namespace std;
inline void * operator new(size_t size)
inline void* operator new(size_t size)
struct complex
~complex()
};int main(void)
執行結果
分析這裡 malloc 的位址是…50 但最終pi 的位址是…58 ,因為返回時,編譯器對位址進行了+8(編譯器實現,過載時不需要實現) ,而這8個位元組剛好存放的就是 2 ,物件的個數,再呼叫delete 時會檢查高sizeof(size_t)位存放的數值,從高位址向低位址對物件呼叫析構函式。
同樣的過載operator delete(void* ptr) 時也存在編譯器預先做好的工作,當過載 operator delete(void* ptr) 時當每個物件的析構函式都已經呼叫完成後才會呼叫該operator delete函式。
C 記憶體管理 C 記憶體分類
c 記憶體管理 記憶體分類 moakap 在編寫程式過程中,程式設計師必須清楚程式記憶體的分配機制,合理進行記憶體管理,這樣才能得到高效的程式。同時,如果對c 記憶體分配基本概念不理解,使用不當,一方面浪費了寶貴的記憶體資源,降低了程式執行效率,另一方面還會造成程式中意想不到的錯誤。在 c 程式中,...
C 記憶體管理
在嵌入式系統中使用c 的乙個常見問題是記憶體分配,即對new 和 delete 操作符的失控。具有諷刺意味的是,問題的根源卻是c 對記憶體的管理非常的容易而且安全。具體地說,當乙個物件被消除時,它的析構函式能夠安全的釋放所分配的記憶體。這當然是個好事情,但是這種使用的簡單性使得程式設計師們過度使用n...
c 記憶體管理
這裡對我暫時所了解的記憶體機制做個記錄,以後再補。首先是記憶體分配 記憶體主要分為3個部分 一是從靜態儲存區域分配。編譯時分配好,主要存放全域性變數,static變數,程式結束釋放。二是從堆疊區域分配。函式內區域性變數存放的地方。隨變數生命週期自動釋放。效率較高,但大小有限。三是從記憶體池分配,即從...