Почему программисты на C ++ должны минимизировать использование «нового»? - PullRequest
815 голосов
/ 28 июня 2011

Я наткнулся на вопрос переполнения стека Утечка памяти при использовании std :: string при использовании std :: list , и в одном из комментариев говорится следующее:

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

Я не совсем уверен, что он имеет в виду. Почему объекты должны создаваться по значению в C ++ как можно чаще, и какое это имеет внутреннее значение? Я неправильно истолковал ответ?

Ответы [ 18 ]

11 голосов
/ 29 июня 2011

Одна заметная причина, по которой следует избегать чрезмерного использования кучи, связана с производительностью, особенно с производительностью механизма управления памятью по умолчанию, используемого C ++. Хотя в обычном случае выделение может быть довольно быстрым, выполнение большого количества new и delete для объектов неоднородного размера без строгого порядка приводит не только к фрагментации памяти, но также усложняет алгоритм выделения и может полностью разрушить производительность в определенных случаях.

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

Лучше все же избежать проблемы в целом. Если вы можете положить его в стек, сделайте это.

10 голосов
/ 28 июня 2011

Я склонен не соглашаться с идеей использования нового «слишком много». Хотя использование оригинального плаката новых с системными классами немного нелепо. (int *i; i = new int[9999];? Действительно? int i[9999]; намного яснее.) Я думаю , что - это то, что получало козу комментатора.

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

Однако, когда вы работаете со своими собственными классами / объектами (например, классом Line первоначального автора), вы должны сами начать думать о таких проблемах, как использование памяти, сохранение данных и т. Д. На этом этапе разрешение нескольких ссылок на одно и то же значение неоценимо - оно допускает такие конструкции, как связанные списки, словари и графики, где несколько переменных должны не только иметь одно и то же значение, но и ссылаться на точно такой же объект в памяти. Однако класс Line не имеет ни одного из этих требований. Таким образом, исходный код плаката фактически не нуждается в new.

10 голосов
/ 28 июня 2011

Я думаю, что постер хотел сказать You do not have to allocate everything on theheap вместо stack.

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

3 голосов
/ 28 июня 2011

Две причины:

  1. В этом случае нет необходимости. Вы делаете свой код без необходимости более сложным.
  2. Он выделяет пространство в куче, и это означает, что вы должны запомнить delete позже, иначе это вызовет утечку памяти.
2 голосов
/ 05 июля 2015

new - это новый goto.

Вспомните, почему goto так поносят: хотя это мощный низкоуровневый инструмент для управления потоком, люди часто используют его излишне сложными способамиэто сделало код трудным для подражания.Кроме того, самые полезные и простые для чтения шаблоны были закодированы в операторах структурированного программирования (например, for или while);конечный эффект заключается в том, что код, в котором goto является подходящим способом, довольно редок; если у вас возникает соблазн написать goto, вы, вероятно, делаете что-то плохо (если вы не действительно знаете, что вывы делаете).

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

Я бы даже сказал, что new хуже чем goto, из-за необходимости сопряжения new и delete операторов.

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

1 голос
/ 22 марта 2019

Еще один момент ко всем приведенным выше правильным ответам, это зависит от того, какое программирование вы делаете.Например, разработка ядра в Windows -> Стек строго ограничен, и вы, возможно, не сможете воспринимать ошибки страницы, как в пользовательском режиме.

В таких средах предпочтительны вызовы нового или C-подобного API и дажеобязательно.

Конечно, это всего лишь исключение из правила.

1 голос
/ 05 июля 2011

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

Другой сценарий - библиотека, которую мы используем, обеспечивает семантику значений и делает ненужным динамическое размещение.Хороший пример - Std::string.

Однако для объектно-ориентированного кода использование указателя - что означает использование new для его предварительного создания - обязательно.Чтобы упростить управление ресурсами, у нас есть десятки инструментов, которые делают его максимально простым, например, умные указатели.Объектно-ориентированная парадигма или универсальная парадигма предполагает семантику значений и требует меньше или не требует new, как указано в постерах в другом месте.new много, так как это типичный код OO.

0 голосов
/ 28 июня 2011

new выделяет объекты в куче. В противном случае объекты размещаются в стеке. Посмотрите разницу между двумя .

...