C++ C++;:行为类似于calloc的新呼叫?

C++ C++;:行为类似于calloc的新呼叫?,c++,new-operator,calloc,C++,New Operator,Calloc,我可以打电话给new让它像calloc那样清空内存吗?没有。默认情况下,它将始终初始化已分配的项,而在基本体的情况下,该项不起任何作用。您必须使用std::uninitialized_fill_n call或类似方法进行后续操作。否。您必须手动将内存清零。请记住,new不仅仅是分配内存,还包括通过构造函数初始化。这就是calloc在C语言中很方便的地方(C语言没有初始化函数)。您可以自由地在new上编写包装器,甚至可以使用calloc,但大多数情况下,对于非POD对象,这没有多大意义。不。也不要

我可以打电话给
new
让它像
calloc
那样清空内存吗?

没有。默认情况下,它将始终初始化已分配的项,而在基本体的情况下,该项不起任何作用。您必须使用std::uninitialized_fill_n call或类似方法进行后续操作。

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

不。也不要想做类似的事情:

YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
#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); 
}
你最终可能会毁掉你的VTABLE(如果你的类有VTABLE的话)


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

不,但是创建一个类似于calloc的新版本相当容易。这可以用与实现new的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;
}
现在,您可以执行以下操作以获得新的零d内存

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

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

您可以对操作符
new
执行全局重载,并让它从
calloc()
中获取原始内存。这样,在构造函数开始运行之前,内存就会被擦除,因此不会出现任何问题

任何重写new的类都不会获得基于特殊的
calloc()
new
,但无论如何,该类都应该正确地初始化自己

不要忘记覆盖
new
delete
以及阵列版本

比如:

YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
#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); 
}
#包括//for std::bad\u alloc
#包括
#包括//for calloc()和free()
void*运算符新(大小\u t大小)
{
void*p=calloc(尺寸,1);
如果(p==0)//分配成功了吗?
抛出std::bad_alloc();
返回p;
}
void运算符删除(void*p)
{
自由基(p);
}
void*运算符新[](大小\u t大小)
{
void*p=calloc(尺寸,1);
如果(p==0)//分配成功了吗?
抛出std::bad_alloc();
返回p;
}
void运算符delete[](void*p)
{
自由基(p);
}
请注意,这些简单的版本并不完全是它们应该是什么样的-
new
操作符应该在一个循环中运行,调用
new\u处理程序
(如果安装了),并且只有在没有
new\u处理程序的情况下才会抛出
bad\u alloc
异常。或者诸如此类的,我得查一下,以后再更新


哦,您可能还想覆盖
no\u-throw
版本。

如果您不坚持使用
new
,您可以简单地使用vector:
vector buffer;调整缓冲区大小(新闻大小),内容将归零。

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);
    }
}
如果愿意,您可以覆盖全局新运算符。

您可以说:

vector <char> v( 100, 0 );

注意,这也使您不必调用delete来释放分配的内存。

与一些人在回答中所说的相反,这是可能的

char * c = new char[N]();
将零初始化所有字符(实际上,它被称为值初始化。但值初始化将是对标量类型数组的所有成员的零初始化)。如果那是你想要的

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

struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;
这不是什么延伸什么的。它在C++98中的工作方式和行为方式也相同。就在那里,它被称为默认初始化,而不是值初始化。但是,对于标量或标量或POD类型的数组,在这两种情况下都会执行零初始化

我使用宏:

#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();
要使用它:

Whatever* myWhatever = newclear(Whatever);

(这使用了“placement new”,就像这里的其他解决方案一样)

我不知道;如果他真的那么想射中自己的脚,阻止他是合乎道德的吗?:-)一定要在课堂上分配和设置你的记忆。不要依赖memset。它在很多情况下都是有效的,但是它在规范中是“未定义的”。尝试用数组——它不起作用(至少对于ISO C++——也许有些扩展的编译器可能允许它)。如果丹文想要更多关于这个主题的信息。还可以用于创建对象缓存(想想linux内核板缓存)s/opeartor/operator/;)可能要将其作为警告,请确保实例化
const zeromemory\u t zeromemory在一个编译单元中。@ephemient,修复了拼写错误。奇怪的是,仅在.cpp文件中定义的值怎么可能包含在多个编译单元中?我的意思是:如果在多个.cpp文件中包含“SomeFile.h”,则只应在一个.cpp文件中写入“const zeromemory”—不多也不少—如果它们要链接在一起。@ephemient,明白了。我的意思是SomeFile.h和SomeFile.cpp是一对,只做一次。可能应该调用它AllocUtil.h和AllocUtil.cpp或类似的名称,以明确在这种情况下定义了虚拟方法的类会发生什么?没有异常情况发生-构造函数正常运行。只是构造器工作的原始内存总是被清除。我每天都从你的帖子中学到新的东西!顺便说一句,你知道为什么不允许使用new[N](42)吗?T()是一种特殊的形式:值初始化或(在c++98中是什么)默认初始化T(42),但是,它是直接初始化,并且不适用于阵列这是我正在寻找的特定场景