2009-04-30 50 views

回答

70

與此相反,有人在回答中說,可能。

char * c = new char[N](); 

將零初始化所有字符(在現實中,它被稱爲值初始化。但值初始化將是零初始化標量類型的數組的所有成員)。如果那就是你的追求。

值得說明的是它也工作了(陣列)類的類型,而用戶聲明的構造在這種情況下,他們中的任何成員的值初始化:

struct T { int a; }; 
T *t = new T[1](); 
assert(t[0].a == 0); 
delete[] t; 

這不是一些擴展或東西。它在C++ 98中的工作方式和行爲方式也一樣。就在那裏,它被稱爲默認初始化,而不是值初始化。然而,零初始化在標量或POD類型的標量或數組的兩種情況下完成。

2

沒有。它總是默認初始化分配的項目,這在基元的情況下什麼也不做。你必須用std :: uninitialized_fill_n調用或類似的方法來跟蹤它。

0

No.You必須手動調零存儲器出來。請記住,new不僅僅是分配內存,還涉及通過構造函數進行初始化。這是calloc在C中的方便之處(它沒有初始化函數)。你可以自由地編寫一個包裝,通過new或甚至使用calloc,但大多數時間非POD對象這沒有多大意義。

5

號也甚至不認爲做這樣的事情的:

YourClass *var = new YourClass; 
memset(var, 0, sizeof(YourClass)); 

你可能最終搗毀你的VTABLE(如果你的類有一個)。

我會建議使用構造函數來清除類的內部存儲器(變量)。

+3

我不知道;如果他真的想用自己的腳踢得那麼糟糕,阻止他是否合乎道德? :-) – 2009-04-30 18:47:43

+0

絕對分配和設置你的班級內存。不要依賴memset。它在很多情況下都有效,但在規範中「未定義」。 – 2009-04-30 18:48:37

+0

@MWWafflestic:不錯的一個! :-) – 2009-04-30 18:52:33

11

沒有,但它很容易創建就像釋放calloc一個新版本。它的實現方式與新版本的新版本的實現方式非常相似。

SomeFile.h

struct zeromemory_t{}; 
extern const zeromemory_t zeromemory; 
void* __cdcel operator new(size_t cbSize, const zeromemory_t&); 

SomeFile.cpp

const zeromemory_t zeromemory; 

void* _cdecl operator new(size_t cbSize, const zeromemory_t&) 
{ 
    void *mem = ::operator new(cbSize); 
    memset(mem,0,cbSize); 
    return mem; 
} 

現在,您可以執行以下操作來獲得新的與zero'd內存

MyType* pMyType = new (zeromemory) MyType(); 

另外你需要做其他有趣的事情,比如define new [],這也是相當直接的。

+2

只是爲了指出這是正式名稱是安置新的。如果丹文想要更多關於這個問題的信息。也可以用於創建對象緩存(想想linux內核slab緩存) – 2009-04-30 18:54:49

+2

s/opeartor/operator /;)可能希望將其作爲警告,確保在一個編譯單元中實例化「const zeromemory_t zeromemory;」。 – ephemient 2009-04-30 20:13:04

+0

@ephemient,修正拼寫錯誤。好奇的是,如何將僅在.cpp文件中定義的值包含在多個編譯單元中? – JaredPar 2009-04-30 20:21:49

2

你可以做運營商new的全球超載,並讓它從calloc()搶原始內存。這樣在構造函數運行之前內存就會被擦除,所以這裏沒有問題。

任何自己重寫新的類都不會得到您的特殊calloc()-based new,但是該類應該正確初始化自己。

不要忘記同時重寫newdelete和陣列版本...

喜歡的東西:

#include <exception> // for std::bad_alloc 
#include <new> 
#include <stdlib.h> // for calloc() and free() 

void* operator new (size_t size) 
{ 
void *p=calloc(size, 1); 
if (p==0) // did allocation succeed? 
    throw std::bad_alloc(); 
return p; 
} 


void operator delete (void *p) 
{ 
free(p); 
} 

void* operator new[] (size_t size) 
{ 
void *p=calloc(size, 1); 
if (p==0) // did allocation succeed? 
    throw std::bad_alloc(); 
return p; 
} 

void operator delete[] (void *p) 
{ 
free(p); 
} 

注意,這些簡單的版本不太正是他們應該是什麼 - 在new經營者應在一個循環中運行調用new_handler(如果已安裝),只拋出bad_alloc異常,如果沒有new_handler。或者類似的,我將不得不查看並稍後更新。

哦,你可能也想重寫no_throw版本,以及。

0

如果你不堅持使用new,你可以簡單地使用矢量:vector<char> buffer; buffer.resize(newsize);,內容將被清零。

0

是的。

int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5 

對於數組,您可以使用類似memset的東西。對於Windows使用ZeroMemory或SecureZeroMemory。

編輯:請參閱@ litb的帖子,他展示瞭如何使用上面的非直接初始化將數組初始化爲0。

0
class MyClass { 
    public: 
    void* operator new(size_t bytes) { 
     return calloc(bytes, 1); 
    } 
} 

如果你喜歡,你可以重寫全局new操作符。

0

你可以說:

vector <char> v(100, 0); 

它可以創建新的100個字符的連續陣列,並將它們全部初始化爲零。然後,您可以,或做訪問與向量的[]操作數組:

char * p = &v[0]; 
p[3] = 42; 

注意這也使你不必調用刪除以釋放分配的內存。

1

我使用宏:

#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE(); 

使用它:

Whatever* myWhatever = newclear(Whatever); 

(這裏採用 「放置新的」 喜歡這裏的一些其他的解決方案)