new
のようにメモリをゼロにするために行うことができる呼び出しはありcalloc
ますか?
11 に答える
一部の人が回答で言っていることとは反対に、それは可能です。
char * c = new char[N]();
すべての文字をゼロ初期化します (実際には、値の初期化と呼ばれます。ただし、値の初期化は、スカラー型の配列のすべてのメンバーに対してゼロ初期化になります)。それがあなたが求めているものなら。
ユーザーがコンストラクターを宣言していないクラス型 (の配列) に対しても機能することに注意してください。この場合、それらのメンバーは値が初期化されます。
struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;
拡張機能などではありません。C++98 でも同じように機能し、動作しました。値の初期化ではなく、デフォルトの初期化と呼ばれていました。ただし、ゼロの初期化は、スカラーまたはスカラーまたは POD 型の配列の両方の場合に行われます。
いいえ、calloc のように機能する新しいバージョンを作成するのはかなり簡単です。これは、スローしないバージョンの new を実装するのとほぼ同じ方法で実行できます。
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;
}
これで、ゼロ化されたメモリで新しいものを取得するために次のことができます
MyType* pMyType = new (zeromemory) MyType();
さらに、かなり単純な define new[] など、他の楽しいことを行う必要があります。
いいえ。次のようなことも考えないでください。
YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
VTABLE を破棄してしまう可能性があります (クラスに VTABLE がある場合)。
コンストラクターを使用して、クラスの内部メモリ (変数) をクリアすることをお勧めします。
いいえ。割り当てられたアイテムは常にデフォルトで初期化されますが、プリミティブの場合は何もしません。std::uninitialized_fill_n 呼び出しなどでフォローアップする必要があります。
演算子のグローバル オーバーロードを実行してnew
、calloc()
. このようにして、コンストラクターが実行される前にメモリが消去されるため、問題はありません。
new を独自にオーバーライドするクラスは、特別なcalloc()
-basednew
を取得しませんが、そのクラスはとにかく正しく初期化する必要があります。
new
とdelete
と 配列バージョンの両方をオーバーライドすることを忘れないでください...
何かのようなもの:
#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
ああ、バージョンもオーバーライドしたいかもしれません。
私はマクロを使用します:
#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();
それを使用するには:
Whatever* myWhatever = newclear(Whatever);
(これは、ここでの他のソリューションと同様に「新しい配置」を使用します)
いいえ、メモリを手動でゼロにする必要があります。new
メモリを割り当てるだけでなく、コンストラクターを介して初期化することも忘れないでください。これはcalloc
、C (初期化関数を持たない) で便利な場所です。ラッパーを自由に記述しnew
たり、 を使用したりすることもできますcalloc
が、ほとんどの場合、非 POD オブジェクトの場合、これはあまり意味がありません。
の使用を主張しない場合はnew
、単純に vector:vector<char> buffer; buffer.resize(newsize);
を使用できます。コンテンツはゼロになります。
はい。
int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5
配列の場合は、memset などを使用できます。Windows の場合、ZeroMemory または SecureZeroMemory を使用します。
編集: @litb の投稿を参照してください。彼は、上記のような非直接初期化を使用して配列を 0 に初期化する方法を示しています。
class MyClass {
public:
void* operator new(size_t bytes) {
return calloc(bytes, 1);
}
}
また、必要に応じて、グローバルな new 演算子をオーバーライドできます。
あなたは言うことができます:
vector <char> v( 100, 0 );
これにより、新しい文字を使用して100文字の隣接する配列が作成され、すべてがゼロに初期化されます。その後、Vectorの[]オペレーターで配列にアクセスできます。
char * p = &v[0];
p[3] = 42;
これにより、割り当てられたメモリを解放するために delete を呼び出す必要がなくなることにも注意してください。