Когда я должен использовать новое ключевое слово в C++?

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

let memberofLobby = await UserLobby.findOne({username: user.username});

Я предлагаю добавить .exec () в конце строки, чтобы на самом деле выполнить findOne () и в результате получить обещание, как это.

let memberofLobby = await UserLobby.findOne({username: user.username}).exec();

Дайте мне знать, сработало ли это для вас!

261
задан Nick Bolton 3 January 2011 в 06:59
поделиться

10 ответов

Метод 1 (использование new)

  • Выделяет память для объекта на свободное хранилище (Это часто - то же самое как "куча" )
  • , Требует Вас к явно delete Ваш объект позже. (Если Вы не удаляете его, Вы могли бы создать утечку памяти)
  • , Память остается выделенной до Вас delete это. (т.е. Вы могли return объект, что Вы создали использование new)
  • , пример в вопросе будет память утечки , если указатель не будет delete d; и это должно всегда удаляться , независимо от которого путь управления взят, или если исключения выдаются.

Метод 2 (не использование new)

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

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

Некоторые легкие случаи:

  • , Если Вы не хотите волноваться о вызове delete, (и потенциал для порождения утечки памяти ) Вы не должны использовать new.
  • , Если требуется возвратить указатель на объект от функции, необходимо использовать new
291
ответ дан Daniel LeCheminant 23 November 2019 в 02:36
поделиться

Между двумя существует важное различие.

Все не выделенное с new ведет себя во многом как типы значения в C# (и люди часто говорят, что те объекты выделяются на стеке, который является, вероятно, наиболее распространенным / очевидным случаем, но не всегда верный. Более точно объекты, выделенные, не используя new, имеют продолжительность автоматического хранения , Все выделенное с new выделяется на "куче", и указатель на него возвращается, точно как ссылочные типы в C#.

Что-либо выделенное на стеке должно иметь постоянный размер, определенный во время компиляции (компилятор должен установить указатель вершины стека правильно, или если объект является членом другого класса, это должно скорректировать размер того другого класса). Вот почему массивы в C# являются ссылочными типами. Они должны быть, потому что со ссылочными типами, мы можем решить во времени выполнения сколько памяти для просьбы. И то же применяется здесь. Только массивы с постоянным размером (размер, который может быть определен во время компиляции) могут быть выделены с продолжительностью автоматического хранения (на стеке). Динамично измеренные массивы должны быть выделены на "куче" путем вызова new.

(И это - то, где любое подобие остановкам C#)

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

средства продолжительности Автоматического хранения точно, на что это походит, продолжительность переменной обрабатывается автоматически. В отличие от этого, что-либо выделенное на "куче" должно быть вручную удалено Вами. Вот пример:

void foo() {
  bar b;
  bar* b2 = new bar();
}

Эта функция создает три стоимости достойной рассмотрения:

На строке 1, это объявляет переменную b из типа bar на стеке (автоматическая продолжительность).

На строке 2, это объявляет bar указатель b2 на стеке (автоматическая продолжительность), и новые вызовы, выделяя bar объект на "куче". (динамическая продолжительность)

то, Когда функция возвратится, следующее, произойдет: Во-первых, b2 выходит из объема (порядок разрушения всегда является противоположностью порядка конструкции). Но b2 просто указатель, таким образом, ничего не происходит, память, которую он занимает, просто освобождена. И значительно, память это точки к [1 121] (bar экземпляр на "куче") НЕ затронуто. Только указатель освобожден, потому что только указатель имел автоматическую продолжительность. Во-вторых, b выходит из объема, поэтому так как он имеет автоматическую продолжительность, ее деструктор называют, и память освобождена.

И bar экземпляр на "куче"? Это, вероятно, все еще там. Никто не потрудился удалять его, таким образом, мы пропустили память.

От этого примера, мы видим, что что-либо с автоматической продолжительностью , гарантировал , чтобы назвать ее деструктор, когда это выходит из объема. Это полезно. Но что-либо выделенное на "куче" длится, пока мы нуждаемся в нем к и можем быть динамично измерены, как в случае массивов. Это также полезно. Мы можем использовать это для управления нашими выделениями памяти. Что, если класс Foo выделил некоторую память на "куче" в ее конструкторе и удалил ту память в ее деструкторе. Тогда мы могли получить лучший из обоих миров, безопасные выделения памяти, которые, как гарантируют, будут освобождены снова, но без ограничений того, чтобы вынуждать все быть на стеке.

И это в значительной степени точно, как большая часть кода C++ работает. Посмотрите на стандартную библиотеку std::vector, например. Это обычно выделяется на стеке, но может быть динамично измерено и изменено. И это делает это путем внутреннего выделения памяти на "куче" по мере необходимости. Пользователь класса никогда не видит это, таким образом, нет никакого шанса просачивающейся памяти или упущения очистить то, что Вы выделили.

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

Как правило, никогда не используйте новый/удаляющий непосредственно от Вашего кода высокого уровня. Всегда обертывайте его в класс, который может управлять памятью для Вас, и который гарантирует, что это освобождено снова. (Да, могут быть исключения к этому правилу. В частности, интеллектуальные указатели требуют, чтобы Вы звонили new непосредственно и передали указатель на его конструктора, который тогда вступает во владение и удостоверяется delete, назван правильно. Но это - все еще очень важное эмпирическое правило)

114
ответ дан Ondrej Slinták 23 November 2019 в 02:36
поделиться

, Какой метод я должен использовать?

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

Для упрощения нагрузки использования людей управления свободного хранилища изобрели материал как auto_ptr и unique_ptr. Я настоятельно рекомендую смотреть на них. Они могли бы даже помочь к Вашим проблемам ввода;-)

13
ответ дан dirkgently 23 November 2019 в 02:36
поделиться

Без new ключевое слово Вы храните это на стек вызовов . Хранение чрезмерно больших переменных на стеке приведет к переполнение стека .

2
ответ дан vartec 23 November 2019 в 02:36
поделиться

Если Ваша переменная используется только в контексте единственной функции, Вы - более обеспеченное использование переменной стека, т.е. Опции 2. Как другие сказали, Вы не должны управлять временем жизни переменных стека - они созданы и разрушены автоматически. Кроме того, выделение/освобождение переменной на "куче" является медленным для сравнения. Если Ваша функция будет вызываться достаточно часто, то Вы будете видеть огромное повышение производительности если переменные стопки использования по сравнению с переменными "кучи".

Тем не менее существует несколько очевидных экземпляров, где переменные стека недостаточны.

, Если переменная стека имеет место памяти большой емкости, то Вы рискуете переполнять стека. По умолчанию размер стека каждого потока составляет 1 МБ в Windows. Маловероятно, что Вы создадите переменную стека, которая составляет 1 МБ в размере, но необходимо иметь в виду, что использование стека кумулятивно. Если Ваши вызовы функции функция, которая вызывает другую функцию, которая вызывает другую функцию, которая..., переменные стека во всех этих функциях занимают место на том же стеке. Рекурсивные функции могут столкнуться с этой проблемой быстро, в зависимости от того, как глубоко рекурсия. Если это - проблема, можно увеличить размер стека (не рекомендуемый) или выделить переменную на "куче" с помощью нового (рекомендуемого) оператора.

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

1
ответ дан Matt Davis 23 November 2019 в 02:36
поделиться

Вы передаете myClass из функции или ожидаете, что это будет существовать вне той функции? Как некоторые другие сказали, это - все об объеме, когда Вы не выделяете на "куче". При отъезде функции она уходит (в конечном счете). Одна из классических ошибок, сделанных новичками, является попыткой создать локальный объект некоторого класса в функции и возвратить его, не выделяя его на "куче". Я могу не забыть отлаживать такого рода вещь назад в мои более ранние дни, делая C++.

1
ответ дан itsmatt 23 November 2019 в 02:36
поделиться

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

1
ответ дан Timo Geusch 23 November 2019 в 02:36
поделиться

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

0
ответ дан RAGNO 23 November 2019 в 02:36
поделиться

Второй метод создает экземпляр на стеке, наряду с такими вещами как что-то объявил int и список параметров, которые передаются в функцию.

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

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

0
ответ дан greyfade 23 November 2019 в 02:36
поделиться

Если Вы пишете в C++, Вы, вероятно, пишете для производительности. Используя новый и свободное хранилище намного медленнее, чем использование стека (особенно при использовании потоков) поэтому только использует его при необходимости в нем.

Как другие сказали, Вам нужно новый, когда Ваш объект должен жить вне функциональной или области объекта, объект является действительно большим или когда Вы не знаете размера массива во время компиляции.

Кроме того, старайтесь не когда-либо использовать, удаляют. Перенесите свое новое в интеллектуальный указатель вместо этого. Позвольте вызову интеллектуального указателя удалить для Вас.

Существуют некоторые случаи, где интеллектуальный указатель не умен. Никогда не храните станд.:: auto_ptr <> в контейнере STL. Это удалит указатель слишком скоро из-за операций копии в контейнере. Другой случай - когда у Вас есть действительно большой контейнер STL указателей на объекты. повышение:: shared_ptr <> будет иметь тонну скорости наверху, поскольку это ударяет подсчеты ссылок вверх и вниз. Лучший способ пойти в этом случае состоит в том, чтобы поместить контейнер STL в другой объект и дать тому объекту деструктор, который будет звонить, удаляют на каждом указателе в контейнере.

9
ответ дан Zan Lynx 23 November 2019 в 02:36
поделиться
Другие вопросы по тегам:

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