В каких случаях я использую malloc и / или new?


479

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

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


33
Я просто хотел бы добавить напоминание о том, что вы не можете смешивать два стиля - то есть вы не можете использовать new для создания объекта и затем вызывать free () для него, а также пытаться удалить блок, выделенный malloc (). Наверное, очевидно, чтобы сказать это, но тем не менее ...
nsayer

32
Хорошие ответы, все, что я должен добавить (что я не видел), это то, что new / delete вызывает для вас конструктор / деструктор, а malloc / free - нет. Просто стоит упомянуть разницу.
Билл К

В современном C ++ я все еще пытаюсь найти причину для использования.
Рахли

Или не используйте ни один, и используйте std: shared_ptr <T>. Тогда вам не нужно удалять вообще.
Винсент

Ответы:


387

Если вы не вынуждены использовать C, вы никогда не должны использоватьmalloc . Всегда используйте new.

Если вам нужен большой кусок данных, просто сделайте что-то вроде:

char *pBuffer = new char[1024];

Будьте осторожны, хотя это не правильно:

//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;

Вместо этого вы должны сделать это при удалении массива данных:

//This deletes all items in the array
delete[] pBuffer;

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

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

Стоит отметить, что вы не можете смешивать new/ freeи malloc/ delete.

Примечание. Некоторые ответы на этот вопрос неверны.

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

2
Что касается вызова delete foo, когда вы должны вызывать delete [] foo, некоторые компиляторы исправят это автоматически, а не утечки, а другие будут удалять только первую запись и утечки. У меня было несколько таких в некотором коде, и valgrind найдет их для вас.
KPexEA

30
Если вы не используете правильное удаление, результат не определен . Это неверно Тот факт, что это может сделать что-то правильно или работать, иногда просто слепая удача.
Майкл Берр

8
@KPexEA: Даже если некоторые компиляторы могут исправить ваши ошибки, все равно неправильно делать их в первую очередь :) Всегда используйте delete [], где это уместно.
Корона

62
«Если вы не вынуждены использовать C, вы никогда не должны использовать malloc. Всегда используйте new». Почему? Какая здесь победа? Для объектов нам нужна конструкция, но для блоков памяти вы четко документируете два способа сделать ошибки кодирования (чем легче поймать () vs [] в новом и менее легко обнаруживаемый несовпадающий массив по сравнению с масштабатором new и delete). Какова мотивация для использования new / delete для блоков сырой памяти?
Бен Супник

3
@DeadMG: Если кто-то создает массив для использования асинхронной API-функцией, разве не new[]намного безопаснее, чем std::vector? Если он используется new[], единственный способ, которым указатель станет недействительным, будет через явный delete, тогда как память, выделенная для, std::vectorможет быть недействительной, когда вектор изменяется или покидает область видимости. (Обратите внимание, что при его использовании new[]необходимо предусмотреть возможность того, что он не сможет вызвать, deleteесли асинхронный метод все еще находится в состоянии ожидания; если может потребоваться отказаться от асинхронной операции, возможно, потребуется организовать удаление с помощью обратного вызова) ,
Суперкат

144

Краткий ответ: не используйте mallocдля C ++ без веской причины для этого. mallocимеет ряд недостатков при использовании с C ++, который newбыл определен для преодоления.

Недостатки, исправленные новым кодом C ++

  1. mallocне является безопасным в любом смысле. В C ++ вам необходимо привести результат из void*. Это потенциально создает много проблем:

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
  2. Хотя это хуже, чем это. Если речь идет о POD (обычные старые данные), то вы можете использовать их mallocдля выделения памяти, как f2в первом примере.

    Это не так очевидно, если тип POD. Важным фактором является тот факт, что данный тип может измениться с POD на non-POD без каких-либо ошибок компиляции, что потенциально очень трудно для устранения проблем. Например, если кто-то (возможно, другой программист, во время обслуживания, намного позже должен был внести изменение, которое fooбольше не являлось POD, то во время компиляции не появилось бы явной ошибки, как вы надеетесь, например:

    struct foo {
      double d[5];
      virtual ~foo() { }
    };

    сделало бы mallocиз этого f2также плохо, без какой-либо очевидной диагностики. Пример здесь тривиален, но можно случайно ввести non-PODness гораздо дальше (например, в базовый класс, добавив не POD-член). Если у вас есть C ++ 11 / boost, вы можете использовать, is_podчтобы проверить правильность этого предположения и выдать ошибку, если это не так:

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }

    Хотя boost не может определить, является ли тип POD без C ++ 11 или каких-либо других расширений компилятора.

  3. mallocвозвращает, NULLесли распределение не удалось. newбудет бросать std::bad_alloc. Поведение более позднего использования NULLуказателя не определено. Исключение имеет чистую семантику, когда оно выбрасывается и выбрасывается из источника ошибки. Упаковка mallocс соответствующим тестом при каждом вызове кажется утомительной и подверженной ошибкам. (Вы должны только забыть один раз, чтобы отменить всю эту хорошую работу). Исключению может быть разрешено распространяться на уровень, на котором вызывающая сторона способна его разумно обработать, и NULLгораздо труднее его осмысленно передать назад. Мы могли бы расширить нашу safe_foo_mallocфункцию, чтобы вызвать исключение или выйти из программы или вызвать некоторый обработчик:

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
  4. По сути malloc, это функция C и newC ++. В результате, mallocон не очень хорошо работает с конструкторами, он только смотрит на выделение фрагмента байтов. Мы могли бы расширить наше safe_foo_mallocдальнейшее использование размещения new:

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
  5. Наша safe_foo_mallocфункция не очень общая - в идеале нам нужно что-то, что может обрабатывать любой тип, а не только foo. Мы можем добиться этого с помощью шаблонов и шаблонов с переменными параметрами для конструкторов, отличных от заданных по умолчанию:

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };

    Теперь, исправляя все выявленные проблемы, мы фактически заново изобрели newоператор по умолчанию . Если вы собираетесь использовать mallocи размещение, newто вы можете просто использовать newдля начала!


27
Это слишком плохо сделано на C ++ structи classозначает в основном то же самое; Интересно, были бы какие-то проблемы с structрезервированием для POD и, возможно, с classпредположением, что все типы не являются POD. Любые типы, определенные кодом, предшествующим изобретению C ++, обязательно будут POD, поэтому я не думаю, что проблема обратной совместимости будет там. Есть ли преимущества для того, чтобы не-POD-типы объявлялись как, structа не как class?
суперкат

1
@supercat Немного поздно, но, как оказалось, создание structи classвыполнение почти одного и того же было замечательным дизайнерским решением, которое теперь включает в себя замечательную функцию под названием «метаклассы» (от Herb) .
Rakete1111

@ Rakete1111: На первый взгляд, это предложение выглядит так, будто оно предварительно обрабатывает версию языка, в которой используются ключевые слова с префиксом доллара, например $class. Я не уверен , что это имеет отношение к classи structсинонимов, однако.
суперкат

@supercat Система типов была бы более раздвоена. Имея classи имея в structвиду одно и то же, вы можете выполнять произвольные преобразования для них ( $class), не беспокоясь о создании classа structи наоборот.
Rakete1111

@ Rakete1111: Если определенные виды операций и преобразований безопасны для некоторых типов, но не для других, то наличие типа, прямо идентифицирующего это, и наличие компилятора, отклоняющего небезопасные операции и преобразования, может показаться лучше, чем изменение метакласса, использованного в способы, которые подходят только для PODS, молча меняются на не PODS.
суперкат

53

Из C ++ FQA Lite :

[16.4] Почему я должен использовать новый вместо надежного старого malloc ()?

FAQ: новый / удалить вызов конструктора / деструктора; new - это безопасный тип, malloc - нет; new может быть переопределено классом.

FQA: достоинства нового, упомянутые в FAQ, не являются достоинствами, потому что конструкторы, деструкторы и перегрузка операторов являются мусором (смотрите, что происходит, когда у вас нет сборки мусора?), И проблема безопасности типов здесь очень мала (обычно у вас есть привести void *, возвращаемый malloc, к правильному типу указателя, чтобы присвоить его типизированной переменной указателя, что может раздражать, но далеко не «небезопасно»).

О, и использование заслуживающего доверия старого malloc делает возможным использование такого же заслуживающего доверия и старого realloc. Жаль, что у нас нет нового оператора или что-то в этом роде.

Тем не менее, new не является достаточно плохим, чтобы оправдать отклонение от общего стиля, используемого в языке, даже когда язык - C ++. В частности, классы с нетривиальными конструкторами будут вести себя фатально, если вы просто неправильно размещаете объекты. Так почему бы не использовать новое по всему коду? Люди редко перегружают оператора новым, так что, вероятно, он не будет слишком мешать вам. И если они действительно перегружают новые, вы всегда можете попросить их остановиться.

Извините, я просто не смог устоять. :)


7
Это бунт ! Спасибо.
dmckee --- котенок экс-модератора

8
Я не могу воспринимать этот комментарий серьезно, поскольку он явно проецирует предвзятость автора в отношении C ++. C ++ - это язык, используемый для создания ориентированного на производительность программного обеспечения, и сборщик мусора может только нанести ущерб его цели. Я не согласен с вашим полным ответом!
Мигель

1
@ Мигель Вы пропустили шутку.
Дэн Бешард

50

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

void *p = operator new(size);
   ...
operator delete(p);

3
Интересно, я всегда просто выделяю массив беззнаковых символов, когда мне нужен такой буфер необработанных данных.
Грег Роджерс

Осторожно, семантика должна быть такой: p_var = new type (initializer); Не размер.
Брайан Р. Бонди

11
Нет, если вы вызываете оператор new напрямую, тогда требуется количество байтов для выделения в качестве параметра.
Ферруччо

1
Хм, не уверен, я никогда не слышал об этом синтаксисе.
Брайан Р. Бонди

9
Противоположностью operator newявляется operator delete. Это не вполне определенное действие для вызова deleteвыражения с типом void*.
CB Bailey

33

Используйте mallocи только для выделения памяти, которая будет управляться с-центрическими библиотеками и API. Используйте и (и варианты) для всего, что вы контролируете.free newdelete[]


10
Также обратите внимание, что хорошо написанная C-библиотека скрывает malloc и освобождает внутренне, именно так должен работать C-программист.
Дакав

@ dmckee у вас есть пример C ++, использующий c-centric библиотеки от malloc и free?
Мильсма

1
@Dacav: если функция C примет указатель на объект, который ей нужно будет продолжать использовать после завершения функции, и вызывающая сторона не сможет узнать, когда объект все еще нужен, это было бы совершенно разумно для функции чтобы указать, что указатель должен быть создан с malloc. Точно так же, если функции, подобной функции, strdupнеобходимо создать объект и вернуть его вызывающей стороне, совершенно разумно указать, что вызывающая сторона должна вызывать freeобъект, когда он больше не нужен. Как такие функции могли бы избежать использования вызывающей стороны malloc / free?
Суперкат

@supercat, что-то неправильно в том, что функция C принимает указатель на объекты, так как C вообще не знает об объектах. В целом, я полагаю, что лучший подход состоит в том, чтобы иметь семантические обертки вокруг выделения / освобождения также в Си. Это все еще может быть приемлемым, но менее гибким, если библиотека Си просит, чтобы вызывающий объект предварительно выделил и / или освободил память. Если функция C делает это и требует владения выделенной памятью, вам неявно требуется выделить ее с помощью malloc.
Дакав

@supercat Одним из примеров повседневного пакета, который, я уверен, все использовали, является libgmp. Если вы когда-либо использовали какое-либо шифрование с открытым исходным кодом или программное обеспечение, основанное на таком шифровании (что весьма вероятно), то вы, вероятно, использовали арифметическую библиотеку произвольной точности, которая должна увеличивать и уменьшать свои собственные внутренние данные. Это делается с помощью функции инициализации ... и тогда вы удивляетесь, как вы используете код C, который является libgmp, в C ++, без перекомпиляции его в C ++? Теперь с этим (линкера) в виду, думать об этом ... почему бы любой разумный человек , когда - либо ставить mallocв C ++?
аутист

31

новый против malloc ()

1) newявляется оператором , а malloc()является функцией .

2) newвызывает конструкторы , пока malloc()не вызывает.

3) newвозвращает точный тип данных , а malloc()возвращает void * .

4) newникогда не возвращает NULL (будет сбрасывать при ошибке), в то время как malloc()возвращает NULL

5) Перераспределение памяти не обрабатываются , newа malloc()может ,


6
Привет, Для пункта 4), new может быть проинструктирован, чтобы возвратить NULL в случае неудачи. char* ptr = new (std::nothrow) char [323232];
Сингх

1
6) new создает из аргументов конструктора, в то время как malloc использует размер.
Эван Моран

есть также newфункция
Ма Мин

Если бы вы были настолько склонны к C, чтобы перераспределять , я надеюсь, что вы используете reallocвместо malloc, и начнете с переменной-указателя, инициализированной в NULL. С другой стороны, если вам нужен кусок памяти с изменяемым размером в C ++, я бы предложил, std::vectorа не realloc... тот или файл.
аутист

19

Чтобы ответить на ваш вопрос, вы должны знать разницу между mallocиnew . Разница проста:

malloc выделяет память , а new выделяет память И вызывает конструктор объекта, для которого вы выделяете память.

Таким образом, если вы не ограничены C, вы никогда не должны использовать malloc, особенно когда имеете дело с объектами C ++. Это был бы рецепт взлома вашей программы.

Также разница между freeи deleteсовершенно одинакова. Разница в том, что deleteвызовет деструктор вашего объекта в дополнение к освобождению памяти.


13

Есть одна большая разница между mallocи new. mallocвыделяет память. Это хорошо для C, потому что в C кусок памяти является объектом.

В C ++, если вы не имеете дело с типами POD (которые похожи на типы C), вы должны вызвать конструктор в ячейке памяти, чтобы фактически иметь там объект. Типы не POD очень распространены в C ++, так как многие функции C ++ делают объект автоматически не POD.

newвыделяет память и создает объект в этой области памяти. Для не POD-типов это означает вызов конструктора.

Если вы делаете что-то вроде этого:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

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

Если, с другой стороны, вы делаете:

non_pod_type* p = new non_pod_type();

Вы получаете указатель, который всегда действителен, потому что newсоздал объект.

Даже для типов POD между ними есть существенная разница:

pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;

Этот фрагмент кода выведет неуказанное значение, потому что созданные объекты POD mallocне инициализируются.

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

pod_type* p = new pod_type();
std::cout << p->foo; // prints 0

Если вы действительно этого хотите, вы можете использовать use newдля получения неинициализированных объектов POD. Смотрите этот другой ответ для получения дополнительной информации об этом.

Другое отличие - поведение при неудаче. Когда не удается выделить память, mallocвозвращает нулевой указатель, а newвыдает исключение.

Первый требует, чтобы вы проверяли каждый указатель, возвращенный перед его использованием, в то время как последний всегда будет выдавать действительные указатели.

По этим причинам в коде C ++ вы должны использовать new, а не использовать malloc. Но даже тогда вы не должны использовать new«в открытую», потому что он получает ресурсы, которые вы должны выпустить позже. При использовании newвы должны немедленно передать его результат в класс управления ресурсами:

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak

7

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

Например:

 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

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

Итак, когда нам нужен 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 ГБ?)
  • У вас есть инструменты, мешающие вам использовать определенные конструкции
  • Вам нужно хранить неполный тип

6

Есть несколько вещей, которые newэтого mallocне делают:

  1. new создает объект, вызывая конструктор этого объекта
  2. new не требует распечатки выделенной памяти.
  3. Для этого не нужно выделять объем памяти, скорее, для этого нужно несколько объектов.

Так что, если вы используете malloc, то вам нужно явно делать вышеперечисленные вещи, что не всегда практично. Кроме того, newможет быть перегружен, но mallocне может быть.


5

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

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

Если вам это не нужно, вы должны придерживаться нового / удалить в C ++.


3

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


3

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


2

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

Например

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

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


1

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


4
new вообще не инициализирует память, хотя есть способы сделать это: см. stackoverflow.com/questions/2204176/… для одного обсуждения об этом.
WJL

0

В следующем сценарии мы не можем использовать 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;
    }
};

0

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

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


0

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


-4

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


2
Вы можете (но почти всегда не должны) использовать mallocв C ++.
междурядный

1
Вы также упустили главное, что вам следует стремиться избегать динамического выделения памяти, если это не делается с помощью умных указателей. Вы просто настраиваете себя на боль другим мудрым
thecoshman
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.