когда использовать новое в C ++? - PullRequest
8 голосов
/ 10 июля 2010

Какова хорошая политика, когда использовать «new» для создания экземпляра класса?Я давно увлекаюсь программированием на C ++, но до сих пор не уверен, когда лучше всего это сделать:

MyClass thing(param1, param2);

по этому поводу:

MyClass* thing;
thing = new MyClass(param1, param2);

Любой совет

Ответы [ 6 ]

22 голосов
/ 10 июля 2010

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

И даже в этом случае никогда не выделяйте вещи динамически raw .Всегда храните их в какой-то оболочке, которая реализует Scope-Bound Resource Management (SBRM, впервые известную под тупым / неуклюжим именем Resource-Acquisition Is Initialization или RAII.) То есть динамические выделения должны храниться в автоматических объектах, которые будут очищатьup автоматически!

Хорошим примером этого является std::vector: вы не можете утечь внутреннюю память до vector, потому что его деструктор запускается в каждом сценарии, когда память должна быть свободна, и он будетосвободи это для тебя.auto_ptr - это первый и единственный интеллектуальный указатель, доступный в стандартной библиотеке, но это довольно плохо.Лучше использовать shared_ptr, либо многие другие популярные интеллектуальные указатели, доступные в Boost и / или TR1 и / или C ++ 0x.

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

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

Итак: автоматическое распределение, когда это возможно, динамическое распределение, когда это необходимо.

5 голосов
/ 10 июля 2010

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

2 голосов
/ 10 июля 2010

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

2 голосов
/ 10 июля 2010

Практическое правило: если оно работает без new, не используйте new.

1 голос
/ 10 июля 2010

Во-первых, задайте себе вопрос, имеет ли смысл копировать объект, когда этого хочет другая функция?

Если имеет смысл скопировать объект, лучше всего создать все настек или переменные-члены, а затем просто передавать копии при необходимости.

Если копировать объект не имеет смысла, вам необходимо использовать форму new, чтобы можно было безопасно передать указатель напредмет.Вы должны использовать указатель (или ссылку), потому что, как уже было отмечено, копировать объект не имеет смысла.

Есть два исключения, о которых я знаю:

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

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

0 голосов
/ 10 июля 2010
 MyClass thing(param1, param2); //memory for thing is allocated on the process stack(static allocation)

 MyClass* thing;
 thing = new MyClass(param1, param2); //memory is allocated dynamically on the heap(free store) for thing

Разница лежит здесь:

 int main()
 { 
   {
    MyClass thing(param1, param2); //thing is local to the scope
   } //destructor called for thing
   //cannot access thing (thing doesn't exist)
 } 

 int main()
 {
   {
     MyClass* thing;
     thing = new MyClass(param1, param2);
   }
  //the object pointed to by thing still exists
   //Memory leak
 }  

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

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