我可以打电话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 的无抛出版本大致相同的方式完成。
一些文件.h
struct zeromemory_t{};
extern const zeromemory_t zeromemory;
void* __cdcel operator new(size_t cbSize, const zeromemory_t&);
一些文件.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[],这也是相当简单的。
不,也不要考虑做类似的事情:
YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
您最终可能会破坏您的 VTABLE(如果您的班级有一个)。
我建议使用构造函数来清除类的内部存储器(变量)。
没有。它总是默认初始化分配的项目,在原语的情况下什么都不做。您必须通过 std::uninitialized_fill_n 调用或类似方法来跟进它。
您可以对运算符进行全局重载,new
并让它从calloc()
. 这样,在构造函数运行之前内存就会被擦除,所以那里没有问题。
任何自己覆盖 new 的类都不会获得您的 special calloc()
-based new
,但是该类无论如何都应该正确初始化自己。
不要忘记覆盖new
anddelete
和数组版本......
就像是:
#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 );
它使用 new 创建一个包含 100 个字符的连续数组,并将它们全部初始化为零。然后,您可以使用向量的 [] 运算符访问数组,或者执行以下操作:
char * p = &v[0];
p[3] = 42;
请注意,这也使您不必调用 delete 来释放分配的内存。