В каких случаях я использую malloc против new? - PullRequest
430 голосов
/ 08 октября 2008

Я вижу, что в C ++ есть несколько способов выделения и освобождения данных, и я понимаю, что когда вы вызываете malloc, вы должны вызывать free, а когда вы используете оператор new, вы должны соединиться с delete, и это ошибка смешивать два (например, вызов free() для чего-то, что было создано с помощью оператора new), но я не понимаю, когда мне следует использовать malloc / free и когда мне следует использовать new / delete в моих реальных программах.

Если вы эксперт C ++, пожалуйста, дайте мне знать практические правила или соглашения, которые вы соблюдаете в этом отношении.

Ответы [ 19 ]

3 голосов
/ 02 апреля 2014

Если вы используете C ++, попробуйте использовать new / delete вместо malloc / calloc, поскольку они являются операторами. Для malloc / calloc вам нужно включить другой заголовок. Не смешивайте два разных языка в одном и том же коде. Их работа одинакова во всех отношениях, оба динамически распределяют память из сегмента кучи в хэш-таблице.

2 голосов
/ 08 октября 2008

Если у вас есть C-код, который вы хотите перенести на C ++, вы можете оставить в нем все вызовы malloc (). Для любого нового кода C ++ я бы рекомендовал использовать вместо него новый.

2 голосов
/ 22 декабря 2018

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

Например:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

Начиная с C ++ 11, у нас есть std::unique_ptr для работы с выделенной памятью, которая содержит владение выделенной памятью. std::shared_ptr был создан для случаев, когда вы должны делиться собственностью. (вам нужно это меньше, чем вы ожидаете в хорошей программе)

Создание экземпляра становится действительно простым:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

C ++ 17 также добавляет std::optional, что может помешать вам выделять память

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

Как только «экземпляр» выходит из области видимости, память очищается. Передача права собственности также проста:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

Так, когда вам все еще нужно new? Почти никогда не начиная с C ++ 11. Большинство из них вы используете std::make_unique, пока не дойдете до точки, где вы нажмете API, который передает владение с помощью необработанных указателей.

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

В C ++ 98/03 вы должны выполнять ручное управление памятью. Если вы в этом случае, попробуйте обновить до более новой версии стандарта. Если вы застряли:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

Убедитесь, что вы правильно отслеживаете владельца, чтобы не было утечек памяти! Семантика перемещения также не работает.

Итак, когда нам нужен malloc в C ++? Единственная действительная причина - выделение памяти и ее инициализация позднее с помощью размещения нового.

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

Несмотря на то, что вышеупомянутое действительно, это можно сделать и через оператора new. std::vector является хорошим примером для этого.

Наконец, у нас все еще есть слон в комнате: C. Если вам приходится работать с библиотекой C, в которой память выделяется в коде C ++ и освобождается в коде C (или наоборот), вы вынуждены использовать malloc / free.

Если вы в этом случае, забудьте о виртуальных функциях, функциях-членах, классах ... Допускаются только структуры с POD.

Некоторые исключения из правил:

  • Вы пишете стандартную библиотеку с продвинутыми структурами данных, для которых подходит malloc
  • Вы должны выделить большие объемы памяти (в оперативной копии файла 10 ГБ?)
  • У вас есть инструменты, которые не позволяют использовать определенные конструкции
  • Вам необходимо хранить неполный тип
1 голос
/ 14 декабря 2016

new инициализирует значения по умолчанию для структуры и правильно связывает ссылки в ней с самим собой.

Е.Г.

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

Таким образом, new struct test_s вернет инициализированную структуру с рабочей ссылкой, в то время как версия malloc не имеет значений по умолчанию и внутренние ссылки не инициализированы.

1 голос
/ 15 августа 2011

С более низкой точки зрения new инициализирует всю память, прежде чем выделять память, тогда как malloc сохранит исходное содержимое памяти.

0 голосов
/ 26 июля 2012

malloc () используется для динамического выделения памяти в C в то время как та же самая работа сделана new () в c ++. Таким образом, вы не можете смешивать соглашения о кодировании 2 языков. Было бы хорошо, если бы вы спросили разницу между calloc и malloc ()

0 голосов
/ 09 октября 2008

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

Использование new/delete поможет улучшить ваш код, поскольку вам не нужно приводить выделенную память к необходимой структуре данных.

0 голосов
/ 29 июля 2017

Редкий случай, чтобы рассмотреть возможность использования malloc / free вместо new / delete, это когда вы выделяете, а затем перераспределяете (простые типы pod, а не объекты), используя realloc, поскольку в C ++ нет функции, аналогичной realloc (хотя это сделано с использованием более подходящего C ++).

0 голосов
/ 17 августа 2012

В следующем сценарии мы не можем использовать new, так как он вызывает конструктор.

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};
...