Подтвердить что ты не робот

Malloc против New для примитивов

Я понимаю преимущества использования new против malloc в С++. Но для конкретных случаев, таких как примитивные типы данных (non array) - int, float и т.д., Быстрее ли использовать malloc, чем новый?

Хотя, всегда рекомендуется использовать "новый" даже для примитивов, если мы выделяем массив, чтобы мы могли использовать delete []. Но для распределения без массива, я думаю, не было бы никакого вызова конструктора для int? Поскольку новый оператор выделяет память, проверяет, назначено ли оно, а затем вызывает конструктор. Но только для примитивов без массива кучи, лучше ли использовать malloc, чем новый? Пожалуйста, сообщите

4b9b3361

Ответ 1

Никогда не используйте malloc в С++. Никогда не используйте new, если вы не используете примитив управления низким уровнем памяти.

Рекомендация:

  • Спросите себя: "Мне нужно динамическое распределение памяти?". Много раз вам может и не понадобиться - предпочитайте значения для указателей и пытайтесь использовать стек.

  • Если вам требуется динамическое распределение памяти, спросите себя, "кто будет владеть выделенной памятью/объектом?".

    • Если вам нужен только один владелец (что очень вероятно), вы должны используйте std::unique_ptr. Это абстракция нулевой стоимости new/delete. (Можно указать другой деаллокатор.)

    • Если вам нужна совместная собственность, вы должны использовать std::shared_ptr. Это не абстракция нулевой стоимости, поскольку она использует атомарные операции и дополнительный "блок управления" для отслеживания всех владельцев.


Если вы имеете дело с массивами, в частности, стандартная библиотека предоставляет две мощные и безопасные абстракции, которые не требуют ручного управления памятью:

  • std::array<T, N>: фиксированный массив элементов N типа T.

  • std::vector<T>: изменяемый размер массива элементов типа T.

std::array и std::vector должны покрывать 99% ваших потребностей в массиве.


Еще одна важная вещь: стандартная библиотека предоставляет std::make_unique и std::make_shared, который должен использоваться всегда для создания экземпляров интеллектуальных указателей. Есть несколько веских причин:

  • Короче - не нужно повторять T (например, std::unique_ptr<T>{new T}), не нужно использовать new.

  • Более безопасное исключение. Они предотвращают потенциальную утечку памяти, вызванную отсутствием четко определенного порядка оценки в вызовах функций. Например.

    f(std::shared_ptr<int>(new int(42)), g())
    

    Может быть оценен в следующем порядке:

    • new int(42)
    • g()
    • ...

    Если g() выбрасывается, int просочится.

  • Более эффективный (с точки зрения скорости выполнения). Это относится только к std::make_shared - использование его вместо std::shared_ptr напрямую позволяет реализации выполнять одно распределение как для объекта, так и для блока управления.

Вы можете найти дополнительную информацию в этом вопросе.

Ответ 2

По-прежнему необходимо использовать malloc и free в С++, когда вы взаимодействуете с API-интерфейсами, указанными с использованием простой C, потому что не гарантировано безопасно использовать free для освобождения памяти, выделенной с помощью operator new (что в конечном итоге используется всеми классами управляемой памяти) и не использовать operator delete для освобождения памяти, выделенной с помощью malloc.

Типичным примером является POSIX getline (не путать с std::getline): он принимает указатель на переменную char *; эта переменная должна указывать на блок памяти, выделенный с помощью malloc (или он может быть NULL, и в этом случае getline будет вызывать malloc для вас); когда вы закончите вызывать getline, вы должны вызвать free для этой переменной.

Аналогично, если вы пишете библиотеку, может иметь смысл использовать С++ внутри, но определить API extern "C" для ваших внешних абонентов, поскольку это дает вам лучшую стабильность бинарного интерфейса и межязычную совместимость. И если вы возвращаете объекты POD, выделенные кучей, для ваших абонентов, вы можете позволить им освободить эти объекты с помощью free; они не могут использовать delete, а их вызов YourLibraryFree, когда нет операций типа деструктора, является нерентабельным.

Также может потребоваться использование malloc при реализации объектов с изменяемым размером контейнера, поскольку для operator new нет эквивалента realloc.

Но, как говорят другие ответы, когда у вас нет такого ограничения интерфейса, связывающего ваши руки, используйте вместо этого один из классов управляемой памяти.

Ответ 3

Всегда лучше использовать new. Если вы используете malloc, вам все равно придется проверять вручную, если пространство выделено.

В современном С++ вы можете использовать интеллектуальные указатели. При make_unique и make_shared вы никогда не вызываете new явно. std::unique_ptr не больше основного указателя, а накладные расходы на его использование минимальны.

Ответ 4

Ответ на "должен ли я использовать new или malloc" правило single responsibillity.

Управление ресурсами должно выполняться типом, который имеет единственную цель.
Эти классы уже существуют, например unique_ptr, vector и т.д.

Непосредственно использование либо malloc, либо new является кардинальным грехом.