40

newのようにメモリをゼロにするために行うことができる呼び出しはありcallocますか?

4

11 に答える 11

78

一部の人が回答で言っていることとは反対に、それ可能です。

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

すべての文字をゼロ初期化します (実際には、値の初期化と呼ばれます。ただし、値の初期化は、スカラー型の配列のすべてのメンバーに対してゼロ初期化になります)。それがあなたが求めているものなら。

ユーザーがコンストラクターを宣言していないクラス型 (の配列) に対しても機能することに注意してください。この場合、それらのメンバーは値が初期化されます。

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

拡張機能などではありません。C++98 でも同じように機能し、動作しました。値の初期化ではなく、デフォルトの初期化と呼ばれていました。ただし、ゼロの初期化は、スカラーまたはスカラーまたは POD 型の配列の両方の場合に行われます。

于 2009-04-30T18:59:31.397 に答える
11

いいえ、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[] など、他の楽しいことを行う必要があります。

于 2009-04-30T18:49:09.690 に答える
4

いいえ。次のようなことも考えないでください。

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

VTABLE を破棄してしまう可能性があります (クラスに VTABLE がある場合)。

コンストラクターを使用して、クラスの内部メモリ (変数) をクリアすることをお勧めします。

于 2009-04-30T18:46:51.550 に答える
2

いいえ。割り当てられたアイテムは常にデフォルトで初期化されますが、プリミティブの場合は何もしません。std::uninitialized_fill_n 呼び出しなどでフォローアップする必要があります。

于 2009-04-30T18:44:52.930 に答える
2

演算子のグローバル オーバーロードを実行してnewcalloc(). このようにして、コンストラクターが実行される前にメモリが消去されるため、問題はありません。

new を独自にオーバーライドするクラスは、特別なcalloc()-basednewを取得しませんが、そのクラスはとにかく正しく初期化する必要があります。

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_allocnew_handler

no_throwああ、バージョンもオーバーライドしたいかもしれません。

于 2009-04-30T18:50:00.030 に答える
1

私はマクロを使用します:

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

それを使用するには:

Whatever* myWhatever = newclear(Whatever);

(これは、ここでの他のソリューションと同様に「新しい配置」を使用します)

于 2011-06-13T15:03:23.917 に答える
0

いいえ、メモリを手動でゼロにする必要があります。newメモリを割り当てるだけでなく、コンストラクターを介して初期化することも忘れないでください。これはcalloc、C (初期化関数を持たない) で便利な場所です。ラッパーを自由に記述しnewたり、 を使用したりすることもできますcallocが、ほとんどの場合、非 POD オブジェクトの場合、これはあまり意味がありません。

于 2009-04-30T18:46:06.497 に答える
0

の使用を主張しない場合はnew、単純に vector:vector<char> buffer; buffer.resize(newsize);を使用できます。コンテンツはゼロになります。

于 2009-04-30T18:50:08.500 に答える
0

はい。

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

配列の場合は、memset などを使用できます。Windows の場合、ZeroMemory または SecureZeroMemory を使用します。

編集: @litb の投稿を参照してください。彼は、上記のような非直接初期化を使用して配列を 0 に初期化する方法を示しています。

于 2009-04-30T18:51:39.120 に答える
0
class MyClass {
    public:
    void* operator new(size_t bytes) {
        return calloc(bytes, 1);
    }
}

また、必要に応じて、グローバルな new 演算子をオーバーライドできます。

于 2009-04-30T18:52:01.663 に答える
0

あなたは言うことができます:

vector <char> v( 100, 0 );

これにより、新しい文字を使用して100文字の隣接する配列が作成され、すべてがゼロに初期化されます。その後、Vectorの[]オペレーターで配列にアクセスできます。

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

これにより、割り当てられたメモリを解放するために delete を呼び出す必要がなくなることにも注意してください。

于 2009-04-30T18:54:43.903 に答える