问题
Is there a call I can make to new
to have it zero out memory like calloc
?
回答1:
Contrary what some are saying in their answers, it is possible.
char * c = new char[N]();
Will zero initialize all the characters (in reality, it's called value-initialization. But value-initialization is going to be zero-initialization for all its members of an array of scalar type). If that's what you are after.
Worth to note that it does also work for (arrays of) class-types without user declared constructor in which case any member of them is value initialized:
struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;
It's not some extension or something. It worked and behaved the same way in C++98 too. Just there it was called default initialization instead of value initialization. Zero initialization, however, is done in both cases for scalars or arrays of scalar or POD types.
回答2:
No but it's fairly easy to create a new version that acts like calloc. It can be done in much the same way that the no-throw version of new is implemented.
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;
}
Now you can do the following to get new with zero'd memory
MyType* pMyType = new (zeromemory) MyType();
Additionally you'd need to do other fun things like define new[] which is fairly straight forward as well.
回答3:
No. Also don't even think of doing something like:
YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
You could end up trashing your VTABLE (if your class has one).
I would recommend using constructors to clear the internal memory (variables) of your class.
回答4:
Nope. It will always default-initialize the allocated item(s), which in the case of primitives does nothing. You'll have to follow it up with a std::uninitialized_fill_n call or similar.
回答5:
You could do a global overload of operator new
and have it grab the raw memory from calloc()
. This way the memory gets wiped before constructors get to run so there's no problems there.
Any class that overrides new on its own will not get your special calloc()
-based new
, but then that class should be initializing itself correctly anyway.
Don't forget to override both new
and delete
and the array versions...
Something like:
#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);
}
Note that these simple versions aren't quite exactly what they should be - the new
operator should run in a loop calling the new_handler
(if one is installed) and only throwing the bad_alloc
exception if there is no new_handler
. Or something like that, I'll have to look it up and update later.
Oh, and you might want to also override the no_throw
version as well.
回答6:
i use a macro:
#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();
to use it:
Whatever* myWhatever = newclear(Whatever);
(this uses "placement new" like some other solutions here)
回答7:
No.You have to manually zero the memory out. Remember, new
is not just about allocating memory, but also about initializing via constructors. This is where calloc
is handy in C (which does not have initializer functions). You are free to write a wrapper over new
or even use calloc
, but most of the time for non-POD objects this doesn't make much sense.
回答8:
if you don't insist using new
, you can simply use vector: vector<char> buffer; buffer.resize(newsize);
and the content will be zeroed.
回答9:
class MyClass {
public:
void* operator new(size_t bytes) {
return calloc(bytes, 1);
}
}
And you can override the global new operator if you like.
回答10:
You can say:
vector <char> v( 100, 0 );
which creates a contiguous array of 100 characters using new, and initialises them all to zero. You can then access the array with vector's [] operator, or by doing:
char * p = &v[0];
p[3] = 42;
Note this also frees you from having to call delete to free the allocated memory.
回答11:
Yes.
int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5
For arrays you can use something like memset. For windows use ZeroMemory or SecureZeroMemory.
Edit: Please see @litb's post, he shows how you can initialize to 0 for arrays using non direct initialization like above.
来源:https://stackoverflow.com/questions/808464/c-new-call-that-behaves-like-calloc