Почему я должен использовать “новый” оператор для инстанцирования класса, и почему?

Просто добавьте еще одно условие:

if (search != "" && (search.startsWith("th") || search.length >= minlength)) {...}
10
задан Peter Mortensen 10 March 2010 в 22:57
поделиться

7 ответов

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

P.S. При необходимости в указателе потому что Вам нужен он для передачи другой функции, просто используйте операцию вычисления адреса:

SomeFunction(&DoSomthing);
27
ответ дан 3 December 2019 в 13:12
поделиться

Вторая форма является так называемым RAII (Приобретение Ресурса Является Инициализацией), шаблон. Это имеет много преимуществ перед первым.

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

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

Так, необходимо предпочесть RAII (вторая опция).

13
ответ дан 3 December 2019 в 13:12
поделиться

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

Выделение на стеке работает действительно хорошо, когда Вы имеете жесткий контроль за время жизни объекта. Это означает, что Вы не собираетесь передавать указатель или ссылку того объекта кодировать за пределами объема локальной функции. Это означает, нет параметры, никакие вызовы COM, никакие новые потоки. Довольно много ограничений, но Вы очистили объект правильно для Вас на нормальном или исключительном выходе от текущей области (Хотя, Вы могли бы хотеть читать на правилах раскручивания стека с виртуальными деструкторами). Самый большой недостаток выделения стека - стек обычно ограничивается 4K или 8K, таким образом, Вы могли бы хотеть быть осторожными, что Вы ставите его.

Выделение на "куче", с другой стороны, потребовало бы Вас к очистке экземпляр вручную. Это также означает, что у Вас есть большая свобода, как управлять временем жизни экземпляра. Необходимо сделать это в двух сценариях: a) Вы собираетесь передать тот объект из объема; или b) объект является слишком большим и выделяет, он на стеке мог вызвать переполнение стека.

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

22
ответ дан 3 December 2019 в 13:12
поделиться

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

  1. Используя new выделит память от "кучи". В случае интенсивного (чрезвычайно частого) выделения и освобождения, Вы будете платить высокой цене:
    • блокировка: "куча" является ресурсом, совместно использованным всеми потоками в Вашем процессе. Операции на "куче" могут потребовать привязки диспетчера "кучи" (сделанный для Вас в библиотеке времени выполнения), который может значительно замедлить вещи.
    • фрагментация: фрагменты "кучи". Можно видеть время, оно берет malloc/new, и освободите/удалите для возврата 10-кратного увеличения. Это соединяет с проблемой блокировки выше, поскольку требуется больше времени для управления фрагментированной "кучей", и больше потоков стоит в очереди, ожидая излечить блокировки. (В Windows существует специальный флаг, который можно установить для диспетчера "кучи", таким образом, он эвристическим образом пытается уменьшить фрагментацию.)
  2. Используя шаблон RAII, память просто взята от стека. Стек является ресурсом на поток, он не фрагментирует, нет никакой блокировки, включенной, и, не может оказаться, играет в Вашем преимуществе с точки зрения местности памяти (т.е. память, кэширующаяся на уровне процессоров.)

Так, при необходимости в объектах для резюме (или ограниченный по объему) промежуток времени определенно используйте второй подход (локальная переменная, на стеке.), Если необходимо обменяться данными между потоками, использовать new/malloc (с одной стороны Вы имеете к, на секундной стрелке эти объекты достаточно обычно долговечны, таким образом, Вы платите чрезвычайно с 0 стоимостью в отношении диспетчера "кучи".)

6
ответ дан 3 December 2019 в 13:12
поделиться

Mark Ransom прав, также необходимо будет инстанцировать с new если Вы собираетесь передать переменную в качестве параметра функции CreateThread-esque.

0
ответ дан 3 December 2019 в 13:12
поделиться

Вторая версия раскрутит стек, если исключение будет выдано. Первое не будет. Я не вижу большого различия иначе.

3
ответ дан 3 December 2019 в 13:12
поделиться

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

Путем создания объекта без нового инициируемый объект хранится на стеке. Если это инициируется с новым, это возвращает указатель на новый объект, который был создан на "куче". Это на самом деле возвращает адрес памяти, который указывает на новый объект. Когда это происходит, Вы должны к памяти управлять переменной. Когда Вы сделаны с помощью переменной, необходимо было бы звонить, удаляют на нем для предотвращения утечки памяти. Без нового оператора, когда переменная выйдет из объема, память будет освобождена автоматически.

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

2
ответ дан 3 December 2019 в 13:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: