本文內容簡短,只為記錄下一次思考過程,事情起源於一句話,「new操作符會呼叫operator new分配記憶體再呼叫建構函式構造物件」,但最近再次看到這句話的時候越看越有疑問,怎麼樣呼叫建構函式??於是就帶著這個問題順便看下operator new和placement new的原始碼加深下印象了。
眾所周知建構函式是在例項化乙個類物件時呼叫,通常我們看到的建構函式是下面這樣用:
classa;
intmain()
上述幾種呼叫方式,不管是在棧上還是堆上例項化乙個類物件時,共同點都是記憶體的申請和類的構造是繫結在一起的。可以試想一下,既然new是先呼叫operator new再呼叫建構函式,那麼這個過程如果我們自己手動呼叫呢:
#include
using
namespace std;
class
aint a;};
intmain()
看起來是沒什麼問題,但實際結果呢?直接編譯出錯,報錯為:
錯誤:錯誤地使用了『a::a』即使更改為顯示呼叫,仍然無法編譯通過:
int
main()
錯誤:不能直接呼叫建構函式『a::a』到這裡就產生了深深的疑問,建構函式不能被顯示呼叫,那new是怎麼呼叫建構函式的?
另一方面,我們知道placement new就是在已分配記憶體上構造物件的,那麼placement new是如何只呼叫建構函式的?
class
aint a;};
intmain()
先來看下operator new和placement new的實現:
_glibcxx_weak_definition void
*operator
new(std::size_t sz) _glibcxx_throw (std::bad_alloc)
return p;
}
// default placement versions of operator new.
inline
void
*operator
new(std::size_t,
void
* __p) _glibcxx_use_noexcept
inline
void
*operator
new[
](std::size_t,
void
* __p) _glibcxx_use_noexcept
// default placement versions of operator delete.
inline
void
operator
delete
(void*,
void
*) _glibcxx_use_noexcept
inline
void
operator
delete
(void*,
void
*) _glibcxx_use_noexcept
可以看到,operator new只是對malloc的一些封裝,而placement new則是什麼都沒做只是把指標返回。至此也基本可以猜到答案了,答案就是編譯器自動呼叫的,想一下也必然是這樣,new是個運算子不是函式,運算子是一種告訴編譯器執行特定的數學或者邏輯操作的符號,又何來定義之說。
下面是一些參考:
thus, for a class type t, a new-expression such as:
pt =
new t;
translates more-or-less into something like:
pt =
static_cast
(operator
new(
sizeof
(t)));
pt->t(
);
[1] calling constructors with placement new -dr.dobb』s
[2] when is the constructor called by 『new』 operator in c++
[3] 原始碼
[4] 原始碼
C new 運算子 用法總結
1.分配記憶體初始化標量型別 如 int 或 double 在型別名後加初始值,並用小括號括起,c 11中也支援大括號。int pi new int 6 double pd new double 9.99 c 11中,支援以下寫法 int pi new int double pd new doubl...
函式呼叫運算子
14.34定義乙個函式物件類,令其執行if then else的操作 該型別的呼叫運算子接受三個引數,它首先檢查第乙個形參,如果成功返回第二個引數的值 如果不成功返回第三個形參的值。includeusing namespace std class if then else int main 14.3...
函式呼叫運算子
struct absint 這個類定義了操作 函式呼叫運算子,它負責接受乙個int型別的實參,然後返回該實參的絕對值。呼叫 int i 42 absint absobj 含有函式運算子的物件 int ui absobj i 將i傳遞給absobj.operator class printstring...