代码之家  ›  专栏  ›  技术社区  ›  nivnad

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

  •  37
  • nivnad  · 技术社区  · 17 年前

    new 让它像内存一样归零 calloc ?

    11 回复  |  直到 13 年前
        1
  •  77
  •   Johannes Schaub - litb    17 年前

    与一些人在回答中所说的相反,它

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

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

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

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

    这不是什么延伸什么的。它在C++98中的工作方式和行为方式也相同。就在那里,它被称为默认初始化,而不是值初始化。但是,对于标量或标量或POD类型的数组,在这两种情况下都会执行零初始化。

        2
  •  11
  •   JaredPar    17 年前

    没有,但是创建一个类似于calloc的新版本相当容易。这可以用与实现new的no-throw版本大致相同的方式来完成。

    struct zeromemory_t{};
    extern const zeromemory_t zeromemory;
    void* __cdcel operator new(size_t cbSize, const zeromemory_t&);
    

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

        3
  •  4
  •   Pablo Santa Cruz    17 年前

    不,也不要想做这样的事情:

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

    你最终可能会毁掉你的VTABLE(如果你的类有VTABLE的话)。

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

        4
  •  2
  •   Promit    17 年前

    不。默认情况下,它将始终初始化已分配的项,而在基本体的情况下,该项不起任何作用。接下来,您必须使用std::uninitialized\u fill\n调用或类似调用。

        5
  •  2
  •   Michael Burr    17 年前

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

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

    别忘了将两者都覆盖 刚出现的 delete 和阵列版本。。。

    #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_handler (如果安装了一个)并且仅抛出 bad_alloc 如果没有,则例外 . 或者诸如此类的,我得查一下,以后再更新。

    no_throw 版本也一样。

        6
  •  1
  •   Christian Specht    15 年前

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

    要使用它:

    Whatever* myWhatever = newclear(Whatever);
    

        7
  •  0
  •   dirkgently    17 年前

    不可以。您必须手动将内存归零。回想起 new 这不仅仅是分配内存,还涉及通过构造函数初始化。这就是 calloc 在C语言中很方便(它没有初始化函数)。你可以自由地在上面写一个包装 刚出现的 甚至使用 分配 ,但大多数情况下,对于非POD对象,这没有多大意义。

        8
  •  0
  •   Francis    17 年前

    如果你不坚持使用 new ,您可以简单地使用矢量: vector<char> buffer; buffer.resize(newsize);

        9
  •  0
  •   Unknown    17 年前
    class MyClass {
        public:
        void* operator new(size_t bytes) {
            return calloc(bytes, 1);
        }
    }
    

        10
  •  0
  •   anon anon    17 年前

    你可以说:

    vector <char> v( 100, 0 );
    

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

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

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

        11
  •  0
  •   Brian R. Bondy    17 年前

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

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

    推荐文章