C++:行为类似于 calloc 的新调用?

发布于 2024-07-19 02:47:42 字数 62 浏览 8 评论 0原文

我可以像 calloc 一样调用 new 来将内存清零吗?

Is there a call I can make to new to have it zero out memory like calloc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

淡紫姑娘! 2024-07-26 02:47:42

与一些人的回答相反,这是可能的。

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

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

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

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

它不是某种扩展或其他东西。 它在 C++98 中的工作方式和行为方式也相同。 就在那里,它被称为默认初始化而不是值初始化。 然而,在这两种情况下,对于标量或标量数组或 POD 类型都会进行零初始化。

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.

贱人配狗天长地久 2024-07-26 02:47:42

不,但创建一个像 calloc 一样的新版本相当容易。 它的实现方式与 new 的无抛出版本的实现方式大致相同。

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;
}

现在您可以执行以下操作来获取内存为零的 new

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

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

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.

找个人就嫁了吧 2024-07-26 02:47:42

不。也不要考虑做这样的事情:

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

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

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

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.

幻想少年梦 2024-07-26 02:47:42

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

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.

北方的韩爷 2024-07-26 02:47:42

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

任何自行重写 new 的类都不会获得基于 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(如果已安装)的循环中运行,并且仅在没有 时抛出 bad_alloc 异常new_handler。 或者类似的事情,我得查一下并稍后更新。

哦,您可能还想覆盖 no_throw 版本。

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.

多情癖 2024-07-26 02:47:42

我使用宏:

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

使用它:(

Whatever* myWhatever = newclear(Whatever);

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

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)

负佳期 2024-07-26 02:47:42

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

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.

时光磨忆 2024-07-26 02:47:42

如果你不坚持使用new,你可以简单地使用vector:vector; 缓冲; buffer.resize(newsize); 并且内容将被清零。

if you don't insist using new, you can simply use vector: vector<char> buffer; buffer.resize(newsize); and the content will be zeroed.

话少心凉 2024-07-26 02:47:42
class MyClass {
    public:
    void* operator new(size_t bytes) {
        return calloc(bytes, 1);
    }
}

如果您愿意,您可以覆盖全局新运算符。

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

And you can override the global new operator if you like.

夜夜流光相皎洁 2024-07-26 02:47:42

您可以说:

vector <char> v( 100, 0 );

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

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

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

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.

携余温的黄昏 2024-07-26 02:47:42

是的。

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

对于数组,你可以使用类似 memset 的东西。 对于 Windows,请使用 ZeroMemory 或 SecureZeroMemory。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文