Я вижу, что в C ++ существует несколько способов выделения и освобождения данных, и я понимаю, что при вызове malloc
вы должны вызывать, free
а когда вы используете new
оператор, вы должны delete
выполнять сопряжение, и смешивать их два - ошибка (например, вызов free()
чего-то, что было создано с new
оператором), но я не знаю, когда мне следует использовать malloc
/ free
и когда я должен использовать new
/ delete
в моих реальных программах.
Если вы являетесь экспертом по С ++, пожалуйста, дайте мне знать практические правила или соглашения, которые вы соблюдаете в этом отношении.
Ответы:
Если вы не вынуждены использовать C, вы никогда не должны использовать
malloc
. Всегда используйтеnew
.Если вам нужен большой кусок данных, просто сделайте что-то вроде:
Будьте осторожны, хотя это не правильно:
Вместо этого вы должны сделать это при удалении массива данных:
new
Ключевое слово путь C ++ сделать это, и это будет гарантировать , что ваш тип будет его конструктор называется .new
Ключевое слово также более типобезопасный аmalloc
не типобезопасные вообще.Единственный способ, которым я мог бы подумать, что было бы полезно использовать
malloc
это, если бы вам нужно было изменить размер буфера данных.new
Ключевое слово не имеют аналогичный способ , какrealloc
. Этаrealloc
функция может более эффективно увеличить размер фрагмента памяти.Стоит отметить, что вы не можете смешивать
new
/free
иmalloc
/delete
.Примечание. Некоторые ответы на этот вопрос неверны.
источник
new[]
намного безопаснее, чемstd::vector
? Если он используетсяnew[]
, единственный способ, которым указатель станет недействительным, будет через явныйdelete
, тогда как память, выделенная для,std::vector
может быть недействительной, когда вектор изменяется или покидает область видимости. (Обратите внимание, что при его использованииnew[]
необходимо предусмотреть возможность того, что он не сможет вызвать,delete
если асинхронный метод все еще находится в состоянии ожидания; если может потребоваться отказаться от асинхронной операции, возможно, потребуется организовать удаление с помощью обратного вызова) ,Краткий ответ: не используйте
malloc
для C ++ без веской причины для этого.malloc
имеет ряд недостатков при использовании с C ++, которыйnew
был определен для преодоления.Недостатки, исправленные новым кодом C ++
malloc
не является безопасным в любом смысле. В C ++ вам необходимо привести результат изvoid*
. Это потенциально создает много проблем:Хотя это хуже, чем это. Если речь идет о POD (обычные старые данные), то вы можете использовать их
malloc
для выделения памяти, какf2
в первом примере.Это не так очевидно, если тип POD. Важным фактором является тот факт, что данный тип может измениться с POD на non-POD без каких-либо ошибок компиляции, что потенциально очень трудно для устранения проблем. Например, если кто-то (возможно, другой программист, во время обслуживания, намного позже должен был внести изменение, которое
foo
больше не являлось POD, то во время компиляции не появилось бы явной ошибки, как вы надеетесь, например:сделало бы
malloc
из этогоf2
также плохо, без какой-либо очевидной диагностики. Пример здесь тривиален, но можно случайно ввести non-PODness гораздо дальше (например, в базовый класс, добавив не POD-член). Если у вас есть C ++ 11 / boost, вы можете использовать,is_pod
чтобы проверить правильность этого предположения и выдать ошибку, если это не так:Хотя boost не может определить, является ли тип POD без C ++ 11 или каких-либо других расширений компилятора.
malloc
возвращает,NULL
если распределение не удалось.new
будет бросатьstd::bad_alloc
. Поведение более позднего использованияNULL
указателя не определено. Исключение имеет чистую семантику, когда оно выбрасывается и выбрасывается из источника ошибки. Упаковкаmalloc
с соответствующим тестом при каждом вызове кажется утомительной и подверженной ошибкам. (Вы должны только забыть один раз, чтобы отменить всю эту хорошую работу). Исключению может быть разрешено распространяться на уровень, на котором вызывающая сторона способна его разумно обработать, иNULL
гораздо труднее его осмысленно передать назад. Мы могли бы расширить нашуsafe_foo_malloc
функцию, чтобы вызвать исключение или выйти из программы или вызвать некоторый обработчик:По сути
malloc
, это функция C иnew
C ++. В результате,malloc
он не очень хорошо работает с конструкторами, он только смотрит на выделение фрагмента байтов. Мы могли бы расширить нашеsafe_foo_malloc
дальнейшее использование размещенияnew
:Наша
safe_foo_malloc
функция не очень общая - в идеале нам нужно что-то, что может обрабатывать любой тип, а не толькоfoo
. Мы можем добиться этого с помощью шаблонов и шаблонов с переменными параметрами для конструкторов, отличных от заданных по умолчанию:Теперь, исправляя все выявленные проблемы, мы фактически заново изобрели
new
оператор по умолчанию . Если вы собираетесь использоватьmalloc
и размещение,new
то вы можете просто использоватьnew
для начала!источник
struct
иclass
означает в основном то же самое; Интересно, были бы какие-то проблемы сstruct
резервированием для POD и, возможно, сclass
предположением, что все типы не являются POD. Любые типы, определенные кодом, предшествующим изобретению C ++, обязательно будут POD, поэтому я не думаю, что проблема обратной совместимости будет там. Есть ли преимущества для того, чтобы не-POD-типы объявлялись как,struct
а не какclass
?struct
иclass
выполнение почти одного и того же было замечательным дизайнерским решением, которое теперь включает в себя замечательную функцию под названием «метаклассы» (от Herb) .$class
. Я не уверен , что это имеет отношение кclass
иstruct
синонимов, однако.class
и имея вstruct
виду одно и то же, вы можете выполнять произвольные преобразования для них ($class
), не беспокоясь о созданииclass
аstruct
и наоборот.Из C ++ FQA Lite :
Извините, я просто не смог устоять. :)
источник
Всегда используйте новое в C ++. Если вам нужен блок нетипизированной памяти, вы можете напрямую использовать оператор new:
источник
operator new
являетсяoperator delete
. Это не вполне определенное действие для вызоваdelete
выражения с типомvoid*
.Используйте
malloc
и только для выделения памяти, которая будет управляться с-центрическими библиотеками и API. Используйте и (и варианты) для всего, что вы контролируете.free
new
delete
[]
источник
malloc
. Точно так же, если функции, подобной функции,strdup
необходимо создать объект и вернуть его вызывающей стороне, совершенно разумно указать, что вызывающая сторона должна вызыватьfree
объект, когда он больше не нужен. Как такие функции могли бы избежать использования вызывающей стороны malloc / free?malloc
в C ++?новый против malloc ()
1)
new
является оператором , аmalloc()
является функцией .2)
new
вызывает конструкторы , покаmalloc()
не вызывает.3)
new
возвращает точный тип данных , аmalloc()
возвращает void * .4)
new
никогда не возвращает NULL (будет сбрасывать при ошибке), в то время какmalloc()
возвращает NULL5) Перераспределение памяти не обрабатываются ,
new
аmalloc()
может ,источник
char* ptr = new (std::nothrow) char [323232];
new
функцияrealloc
вместоmalloc
, и начнете с переменной-указателя, инициализированной вNULL
. С другой стороны, если вам нужен кусок памяти с изменяемым размером в C ++, я бы предложил,std::vector
а неrealloc
... тот или файл.Чтобы ответить на ваш вопрос, вы должны знать разницу между
malloc
иnew
. Разница проста:malloc
выделяет память , аnew
выделяет память И вызывает конструктор объекта, для которого вы выделяете память.Таким образом, если вы не ограничены C, вы никогда не должны использовать malloc, особенно когда имеете дело с объектами C ++. Это был бы рецепт взлома вашей программы.
Также разница между
free
иdelete
совершенно одинакова. Разница в том, чтоdelete
вызовет деструктор вашего объекта в дополнение к освобождению памяти.источник
Есть одна большая разница между
malloc
иnew
.malloc
выделяет память. Это хорошо для C, потому что в C кусок памяти является объектом.В C ++, если вы не имеете дело с типами POD (которые похожи на типы C), вы должны вызвать конструктор в ячейке памяти, чтобы фактически иметь там объект. Типы не POD очень распространены в C ++, так как многие функции C ++ делают объект автоматически не POD.
new
выделяет память и создает объект в этой области памяти. Для не POD-типов это означает вызов конструктора.Если вы делаете что-то вроде этого:
Полученный вами указатель не может быть разыменован, поскольку он не указывает на объект. Вам нужно вызвать конструктор, прежде чем вы сможете его использовать (и это делается с помощью размещения
new
).Если, с другой стороны, вы делаете:
Вы получаете указатель, который всегда действителен, потому что
new
создал объект.Даже для типов POD между ними есть существенная разница:
Этот фрагмент кода выведет неуказанное значение, потому что созданные объекты POD
malloc
не инициализируются.С помощью
new
вы можете указать конструктор для вызова и, таким образом, получить четко определенное значение.Если вы действительно этого хотите, вы можете использовать use
new
для получения неинициализированных объектов POD. Смотрите этот другой ответ для получения дополнительной информации об этом.Другое отличие - поведение при неудаче. Когда не удается выделить память,
malloc
возвращает нулевой указатель, аnew
выдает исключение.Первый требует, чтобы вы проверяли каждый указатель, возвращенный перед его использованием, в то время как последний всегда будет выдавать действительные указатели.
По этим причинам в коде C ++ вы должны использовать
new
, а не использоватьmalloc
. Но даже тогда вы не должны использоватьnew
«в открытую», потому что он получает ресурсы, которые вы должны выпустить позже. При использованииnew
вы должны немедленно передать его результат в класс управления ресурсами:источник
Динамическое размещение требуется только в том случае, если время жизни объекта должно отличаться от области, в которой он создается (это также относится к уменьшению и увеличению области), и у вас есть особая причина, по которой его сохранение по значению не Работа.
Например:
Начиная с C ++ 11 мы имеем
std::unique_ptr
дело с распределенной памятью, которая содержит владение выделенной памятью.std::shared_ptr
был создан для того, когда вы должны делиться собственностью. (вам нужно это меньше, чем вы ожидаете в хорошей программе)Создание экземпляра становится действительно простым:
C ++ 17 также добавляет,
std::optional
что может помешать вам требовать выделения памятиКак только «экземпляр» выходит из области видимости, память очищается. Передача прав собственности также проста:
Так когда же тебе еще нужно
new
? Почти никогда не начиная с C ++ 11. Большинство из них вы используете,std::make_unique
пока не дойдете до точки, где вы попадаете в API, который передает владение через необработанные указатели.В C ++ 98/03 вы должны выполнять ручное управление памятью. Если вы в этом случае, попробуйте обновить до более новой версии стандарта. Если вы застряли:
Убедитесь, что вы правильно отслеживаете владение, чтобы не было утечек памяти! Семантика Move еще не работает.
Итак, когда нам нужен malloc в C ++? Единственная действительная причина заключается в том, чтобы выделить память и инициализировать ее позже путем размещения нового.
Несмотря на то, что вышеупомянутое действительно, это может быть сделано через оператора new.
std::vector
хороший пример для этого.Наконец, у нас еще есть слон в комнате
C
. Если вам приходится работать с C-библиотекой, где память выделяется в коде C ++ и освобождается в коде C (или наоборот), вы вынуждены использовать malloc / free.Если вы в этом случае, забудьте о виртуальных функциях, функциях-членах, классах ... Разрешены только структуры с POD.
Некоторые исключения из правил:
источник
Есть несколько вещей, которые
new
этогоmalloc
не делают:new
создает объект, вызывая конструктор этого объектаnew
не требует распечатки выделенной памяти.Так что, если вы используете
malloc
, то вам нужно явно делать вышеперечисленные вещи, что не всегда практично. Кроме того,new
может быть перегружен, ноmalloc
не может быть.источник
Если вы работаете с данными, которые не нуждаются в построении / уничтожении и требуют перераспределения (например, большого массива целых чисел), то я считаю, что malloc / free - это хороший выбор, поскольку он дает вам realloc, который намного быстрее, чем new-memcpy -delete (это на моем компьютере с Linux, но я думаю, это может зависеть от платформы). Если вы работаете с объектами C ++, которые не являются POD и требуют создания / уничтожения, вы должны использовать операторы new и delete.
Во всяком случае, я не понимаю, почему вы не должны использовать оба (при условии, что вы освобождаете свою незанятую память и удаляете объекты, выделенные с новым), если можете воспользоваться преимуществами ускорения (иногда значительного, если вы перераспределяете большие массивы). POD), который может дать вам realloc.
Если вам это не нужно, вы должны придерживаться нового / удалить в C ++.
источник
Если у вас есть C-код, который вы хотите перенести на C ++, вы можете оставить в нем любые вызовы malloc (). Для любого нового кода C ++ я бы рекомендовал использовать вместо него новый.
источник
Если вы используете C ++, попробуйте использовать new / delete вместо malloc / calloc, поскольку они являются операторами. Для malloc / calloc вам нужно включить другой заголовок. Не смешивайте два разных языка в одном и том же коде. Их работа одинакова во всех отношениях, оба динамически распределяют память из сегмента кучи в хэш-таблице.
источник
new
инициализирует значения по умолчанию для структуры и правильно связывает ссылки в ней с собой.Например
Поэтому
new struct test_s
вернет инициализированную структуру с рабочей ссылкой, в то время как версия malloc не имеет значений по умолчанию, а внутренние ссылки не инициализированы.источник
С более низкой точки зрения, new инициализирует всю память перед предоставлением памяти, тогда как malloc сохранит исходное содержимое памяти.
источник
В следующем сценарии мы не можем использовать new, так как он вызывает конструктор.
источник
Операторы
new
иdelete
могут работать с классами и структурами, тогда какmalloc
иfree
работают только с блоками памяти, которые необходимо преобразовать.Использование
new/delete
поможет улучшить ваш код, так как вам не нужно приводить выделенную память к требуемой структуре данных.источник
Редкий случай использования malloc / free вместо new / delete - это когда вы выделяете, а затем перераспределяете (простые типы pod, а не объекты), используя realloc, поскольку в C ++ нет функции, аналогичной realloc (хотя это можно сделать с помощью больше C ++ подход).
источник
malloc () используется для динамического выделения памяти в C, в то время как та же самая работа выполняется new () в c ++. Таким образом, вы не можете смешивать соглашения о кодировании 2 языков. Было бы хорошо, если бы вы спросили разницу между calloc и malloc ()
источник
malloc
в C ++.