C ++:表现得像calloc的新调用?

时间:2009-04-30 18:43:45

标签: c++ new-operator calloc

我是否可以致电newcalloc内存归零?

11 个答案:

答案 0 :(得分:73)

与某些人在答案中所说的相反, 是可能的。

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

零会初始化所有字符(实际上,它称为值初始化。但是值初始化将为标量类型数组的所有成员进行零初始化)。如果这就是你所追求的。

值得注意的是,它也适用于没有用户声明的构造函数的(类数组)类型,在这种情况下,它们的任何成员都是值初始化的:

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

这不是某种延伸或其他什么。它在C ++ 98中的工作和行为也是一样的。就在那里它被称为默认初始化而不是值初始化。但是,对于标量或标量或POD类型的数组,在两种情况下均进行零初始化。

答案 1 :(得分:11)

不,但创建一个像calloc一样的新版本相当容易。它的实现方式与实现no-throw版本的新方法完全相同。

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();

此外,您还需要做其他有趣的事情,例如定义new [],这也很简单。

答案 2 :(得分:5)

没有。甚至不要想做类似的事情:

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

你最终可能会破坏你的VTABLE(如果你的班级有一个)。

我建议使用构造函数来清除类的内部存储器(变量)。

答案 3 :(得分:2)

不。它总是默认初始化分配的项目,在基元的情况下什么都不做。您必须使用std :: uninitialized_fill_n调用或类似方法进行跟进。

答案 4 :(得分:2)

您可以对运算符new执行全局重载,并从calloc()获取原始内存。这样在构造函数运行之前内存就会被擦除,所以那里没有问题。

任何自己覆盖新内容的类都不会获得基于calloc()的特殊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的循环中运行(如果安装了一个)并且只抛出{{1如果没有bad_alloc,则会出现异常。或类似的东西,我将不得不查找并稍后更新。

哦,您可能还希望覆盖new_handler版本。

答案 5 :(得分:1)

我使用宏:

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

使用它:

Whatever* myWhatever = newclear(Whatever);

(这与其他解决方案一样使用“placement new”)

答案 6 :(得分:0)

不。你必须手动将内存归零。请记住,new不仅仅是分配内存,还包括通过构造函数初始化。这是calloc在C中很方便的地方(没有初始化函数)。您可以自由地在new上写一个包装器,甚至可以使用calloc,但是对于非POD对象,大多数情况下这都没有多大意义。

答案 7 :(得分:0)

如果您不坚持使用new,则只需使用vector:vector<char> buffer; buffer.resize(newsize);即可将内容归零。

答案 8 :(得分:0)

是。

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

对于数组,您可以使用类似memset的内容。对于Windows,使用ZeroMemory或SecureZeroMemory。

编辑:请参阅@ litb的帖子,他展示了如何使用非直接初始化(如上所述)为数组初始化为0。

答案 9 :(得分:0)

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

如果您愿意,可以覆盖全局新操作符。

答案 10 :(得分:0)

你可以说:

vector <char> v( 100, 0 );

使用new创建一个包含100个字符的连续数组,并将它们全部初始化为零。然后,您可以使用vector的[]运算符或执行以下操作来访问数组:

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

请注意,这也使您无需调用delete来释放已分配的内存。