Инициализация класса C ++, содержащая инициализацию переменной класса - PullRequest
13 голосов
/ 02 октября 2008

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

DiagramScene::DiagramScene( int slideNo, QRectF screenRect, MainWindow* parent )
    : QGraphicsScene( screenRect, parent ),
    myParent( parent ), 
    slideUndoImageCurrentIndex(-1),
    nextGroupID(0),
    m_undoInProgress(false),
    m_deleteItemOnNextUndo(0)
    line(0),
    path(0)
{
    /* Setup default brush for background */
    scDetail->bgBrush.setStyle(Qt::SolidPattern);
    scDetail->bgBrush.setColor(Qt::white);
    setBackgroundBrush(scDetail->bgBrush);

}

Ответы [ 8 ]

26 голосов
/ 02 октября 2008
  • Это более эффективно (в общем). Все члены класса инициализируются в конструкторе, независимо от того, явно вы их инициализируете или нет. Если вы не укажете инициализатор, тогда будет запущен конструктор по умолчанию для члена. Если вы присваиваете значение в теле конструктора, то оператор присваивания вызывается снова. Это не относится к скалярным значениям, как в вашем примере, поскольку скалярные значения не имеют конструкторов.
  • Вы не можете случайно присвоить значение дважды в списке инициализатора.
  • Компилятор может проверить, чтобы убедиться, что порядок, в котором вы пишете инициализаторы, соответствует порядку, в котором элементы определены в классе. Стандарт C ++ требует, чтобы члены инициализировались в том порядке, в котором они были объявлены, независимо от того, в каком порядке вы пишете инициализаторы. Проверка компилятором этого порядка гарантирует, что программист знает, в каком порядке будут запускаться инициализаторы (опять же, это важнее для не-POD членов, чем для скаляров).
  • Типы ссылок и const элементы должны быть инициализированы в списке инициализаторов, поскольку вы не можете назначить ссылку или элементу const.
4 голосов
/ 02 октября 2008

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

ПРИМЕЧАНИЕ : бывают случаи, когда списки инициализации требуются для основных типов данных, особенно если тип является константным или ссылочным. Для этих типов данные могут быть инициализированы только один раз, и поэтому они не могут быть инициализированы в теле конструктора. См. эту статью для получения дополнительной информации.

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

Я рекомендую:

  • Вы учитесь любить списки инициализации.
  • Ваш коллега понимает правила порядка инициализации членов (и избегает предупреждений).
3 голосов
/ 02 октября 2008

В дополнение к отличному ответу Грега Хьюгилла - в списке инициализации должны быть установлены постоянные переменные.

2 голосов
/ 02 октября 2008

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

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

См. C ++ FAQ-Lite для более подробной информации

2 голосов
/ 02 октября 2008

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

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

0 голосов
/ 06 мая 2010

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

Когда список инициализатора конструктора обрабатывается компилятором, элементы инициализируются в том порядке, в котором они объявлены в объявлении класса , а не в том порядке, в котором они появляются в списке инициализатора.

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

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

0 голосов
/ 02 октября 2008

Еще одно дополнение к ответу Грега: члены, типы которых не имеют конструктора по умолчанию, должны быть инициализированы в списке инициализации.

0 голосов
/ 02 октября 2008

Взгляните на собранную мудрость в http://web.tiscali.it/fanelia/cpp-faq-en/ctors.html#faq-10.6

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