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 的无抛出版本大致相同的方式完成。

一些文件.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[],这也是相当简单的。

于 2009-04-30T18:49:09.690 回答
4

不,也不要考虑做类似的事情:

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

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

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

于 2009-04-30T18:46:51.550 回答
2

没有。它总是默认初始化分配的项目,在原语的情况下什么都不做。您必须通过 std::uninitialized_fill_n 调用或类似方法来跟进它。

于 2009-04-30T18:44:52.930 回答
2

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

任何自己覆盖 new 的类都不会获得您的 special calloc()-based new,但是该类无论如何都应该正确初始化自己。

不要忘记覆盖newanddelete和数组版本......

就像是:

#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版本。

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

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

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

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

于 2009-04-30T18:54:43.903 回答