Вопрос

Могу ли я кому-нибудь позвонить new чтобы он обнулял память, например calloc?

Это было полезно?

Решение

Вопреки тому, что некоторые говорят в своих ответах, это является возможно.

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 .

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

Кроме того, вам нужно было бы сделать другие забавные вещи, такие как define new [], что также довольно просто.

Нет.Кроме того, даже не думайте делать что-то вроде:

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

В конечном итоге вы можете уничтожить свою виртуальную таблицу (если она есть в вашем классе).

Я бы рекомендовал использовать конструкторы для очистки внутренней памяти (переменных) вашего класса.

Нет.Он всегда будет инициализировать выделенные элементы по умолчанию, что в случае примитивов ничего не делает.Вам нужно будет выполнить это с помощью вызова std::uninitialized_fill_n или аналогичного.

Вы могли бы выполнить глобальную перегрузку operator new и пусть он захватит необработанную память из calloc().Таким образом, память стирается до запуска конструкторов, так что проблем здесь нет.

Любой класс, который сам по себе переопределяет new, не получит вашего специального calloc()-основанный new, но тогда этот класс в любом случае должен правильно инициализироваться.

Не забудьте переопределить оба варианта new и 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 оператор должен выполняться в цикле, вызывающем 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); и содержимое будет обнулено.

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

И вы можете переопределить глобальный оператор new, если хотите.

Вы можете сказать:

vector <char> v( 100, 0 );

который создает непрерывный массив из 100 символов, используя new, и инициализирует их все равными нулю.Затем вы можете получить доступ к массиву с помощью оператора vector [] или выполнив:

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

Обратите внимание, что это также освобождает вас от необходимости вызывать delete, чтобы освободить выделенную память.

ДА.

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

Для массивов вы можете использовать что-то вроде memset.Для Windows используйте ZeroMemory или SecureZeroMemory.

Редактировать: Пожалуйста, смотрите сообщение @litb, он показывает, как вы можете инициализировать 0 для массивов, используя непрямую инициализацию, как описано выше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top