Какой правильный способ создания объектов в C ++? - PullRequest
6 голосов
/ 09 декабря 2011

В C ++ (я использую QT) я могу создать экземпляр класса QString двумя способами:

метод 1

QString str = "my string";

метод 2

QString *str = new QString("my string");

Я знаю, что это связано с указателями. Итак, мои вопросы:

  1. В чем разница между этими двумя?
  2. к какому методу я должен придерживаться?
  3. когда правильно использовать метод 1 и когда правильно использовать метод 2?
  4. в методе 2 я могу уничтожить объект, вызвав delete str;. Как я могу удалить переменную str при использовании метода 1?

Спасибо

Ответы [ 6 ]

5 голосов
/ 09 декабря 2011

Это очень разные вещи.

QString str("my string"); создает объект, время жизни которого автоматически управляется : объект либо доживает до конца своей охватывающей области (если это локальная переменная), либо до конца программы (если это глобальная переменная).

new QString("my string"); создает объект с управляемым вручную временем жизни , также называемым "динамическим объектом" (и возвращает указатель на этот объект). Это означает, что вы несете ответственность за управление временем жизни объекта. Это почти никогда не будет правильным , если вы не пишете компонент библиотеки.

И в этом суть философии C ++: C ++ - это язык для написания библиотек. У вас есть инструменты для написания высококачественных, многократно используемых компонентов. Если и когда вы это сделаете, вам необходимо знать тонкости управления жизненным циклом. Однако с до тех пор, пока не наступит , вы должны использовать существующие компоненты библиотеки. При этом вы обнаружите, что вам почти никогда не потребуется выполнять какое-либо ручное управление.

Используйте динамические контейнеры (векторы, строки, карты и т. Д.) Для хранения данных и построения собственных структур данных. Передайте аргументы по ссылке, если вам нужно изменить объекты в области действия вызывающего. Создавайте сложные классы из более простых компонентов. Если вам действительно нужны динамические объекты, обработайте их с помощью классов-обработчиков unique_ptr<T> или shared_ptr<T>.

Не используйте указатели. Редко используйте new, а delete никогда.

(Дополнительные советы: 1) Никогда не используйте using namespace, если это не для ADL. 2) Если вы не пишете библиотечные компоненты, хорошо спроектированные классы не должны иметь деструкторов, конструкторов копирования или операторов присваивания. Если они это сделают, выделите нарушающую логику в компонент библиотеки с единственной ответственностью, затем см. 2).)

5 голосов
/ 09 декабря 2011
  1. в основном они имеют разные времена жизни: объект, созданный в методе 2, будет жить произвольно долго, пока вы не вызовете delete;в методе 1 он будет создан в стеке и уничтожен при возврате из вызова функции (если есть).во-вторых, метод 2 требует больше работы из-за нетривиального управления памятью.

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

  3. см. 2. выше.в частности, использование метода 1 и сохранение указателя на объект и доступ к нему после его жизни - ловушка.это также возможно с методом 2, но явное уничтожение фокусирует внимание программиста на нем (но все же из-за того, что время жизни не является простым, это вероятная ошибка) ловушка с методом 2 забывает удалить ее, вызывая утечку памяти (или удаляя ее).слишком рано и ссылаясь на него, как описано ранее в этом параграфе)

  4. в методе 1 объект будет автоматически удален при возврате функции.

3 голосов
/ 09 декабря 2011

Когда вы используете первый синтаксис, вы создаете объект с именем str с типом QString и начальным значением "my string".

Во втором объявлении вы создаете указатель типа QString с именем str.

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

2 голосов
/ 09 декабря 2011

Разница в том, что метод один создает QString в стеке, а второй способ создает QString в бесплатном хранилище.(Обратите внимание, что QString s = "hello"; в точности совпадает с QString s("hello");.) Как и говорил parapura rajkumar, всегда делайте 1, когда можете, и 2, когда вы не можете 1. 1. 1005 *

Метод 1 имеет много преимуществ,Не в последнюю очередь автоматическое управление памятью.Память, занятая этим QString, будет автоматически освобождена, когда она выйдет из области видимости, поэтому вам не нужно ничего делать, чтобы освободить ее память.Метод 2 требует, чтобы вы использовали delete, когда вы закончили с ним, чтобы освободить память, или у вас будет утечка памяти.

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

Ситуация, в которой вы должны использовать метод 2, - это когда вам нужен этот самый объект, который длится дольше, чем объем, в котором вы находитесь.d выделите в свободном хранилище new, чтобы оно продолжалось до тех пор, пока вы не вызовете delete и не передадите указатель.

2 голосов
/ 09 декабря 2011

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

Второй метод предназначен для ручного управления памятью - он не будет удален, пока вы не вызовете delete str; Если вы забудете удалить его - это создаст то, что мы называем утечкой памяти!

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

Вы можете найти это полезным: Зачем использовать указатели?

1 голос
/ 09 декабря 2011

когда правильно использовать метод 1 и когда правильно использовать метод 2?

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

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

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

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

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