2015-02-09 3 views
12

Что касается следующего: существуют ли какие-либо причины для одного над другим или они примерно эквивалентны?C++ - инициализация переменных в заголовке vs с помощью конструктора

class Something 
{ 
    int m_a = 0; 
}; 

против

class Something 
{ 
    int m_a; 
    Something(int p_a); 
}; 

Something::Something(int p_a):m_a(p_a){ ... }; 
+4

первого один является новой особенностью C++ 11 – Emadpres

+0

Я не ожидал, что первый код для работы. (edit: ok он делает сейчас) – Aitch

+1

Возможный дубликат [C++ 11 допускает инициализацию нестатического и неконстантного элементов в классе. Что изменилось?] (Http://stackoverflow.com/questions/13662441/c11-allows-in-class-initialization-of-non-static-and-non-const-members-what-c) –

ответ

5

Первая форма является новой для C++ 11 и поэтому на данный момент не очень хорошо поддерживается, особенно если вам необходимо поддерживать множество старых компиляторов.

В противном случае они должны быть примерно эквивалентными при наличии компилятора C++ 11.

+0

Я думал, ve всегда был в состоянии инициализировать 'int' как первую форму. Поддерживает ли C++ 11 инициализацию больше, чем 'int' таким образом?!? –

+0

@ Jonathan Mee Вы всегда можете инициализировать 'static' ints ранее, да. –

+1

@JonathanMee: Нестатическая инициализация членов является новой для C++ 11. Он также расширяет статическую инициализацию члена до любых типов константных литералов, а не только целых чисел. –

9

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

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

0
class Something 
{ 
    int m_a = 0; 
}; 

эквивалентно

class Something 
{ 
    int m_a(0); 
}; 

Итак, делая

class Something 
{ 
    int m_a;// (0) is moved to the constructor 
public: 
    Something(): m_a(0){} 
}; 

дает однородный синтаксис для инициализации, которая требует или не требует ввода времени выполнения.

Лично мне не нравится первая форма, потому что она выглядит как «объявление, а затем назначение», что является полным заблуждением.

+1

За исключением того, что в этом случае 'int m_a (0);' не разрешено. – juanchopanza

+0

Чтобы разработать, только для '= value;' и '{value};' разрешены для инициализаторов членов класса, а не '(value);'. – chris

16

Два приведенных фрагмента кода: не совсем одинаково.

class Something 
{ 
    int m_a = 0; 
}; 

Здесь указывается значение, с которым инициализацию, т.е. 0, во время компиляции.

class Something 
{ 
    int m_a; 
    Something(int p_a); 
}; 

Something::Something(int p_a):m_a(p_a){ ... }; 

И здесь вы делаете это на время выполнения (или, возможно, во время выполнения), со значением p_a не известно, пока конструктор не вызывается.

Следующий фрагмент кода приходит ближе к первому примеру:

class Something 
{ 
    int m_a; 
    Something(); 
}; 

Something::Something() : m_a(0) { /* ... */ }; 

То, что вы должны рассмотреть здесь является то, что в первом случае, значение отображается непосредственно в определении класса. Это может создать ненужную зависимость. Что произойдет, если вам понадобится изменить 0 на 1 позже?Отображение значения непосредственно в определении класса (и, как правило, в заголовочном файле) может привести к перекомпиляции большого количества кода в ситуациях, когда другая форма инициализации позволит избежать этого, поскольку часть Something::Something() : m_a(0) будет аккуратно инкапсулирована в источник файл и не появляется в файле заголовок:

// Something.h - stable header file, never changed 
class Something 
{ 
    int m_a; 
    Something(); 
}; 

// Something.cpp - can change easily 
Something::Something() : m_a(0) { /* ... */ }; 

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

+0

+1 за то, что непреднамеренно вызывают дорогие перекомпиляции - они могут стать довольно дорого довольно быстро. –

1

Разработка ответа Христиана Хакля.

Первая форма позволяет инициализировать m_a и одновременно использовать по умолчанию c'tor. Или вы даже можете быть явным в вашем коде и определить конструктор с default ключевого слова:

class Something 
{  
    int m_a = 0; 

    // explicitly tell the compiler to generate a default c'tor 
    Something() = default; 
}; 

С второй формы, автоматически сгенерированный по умолчанию c'tor оставит m_a неинициализированным, так что если вы хотите инициализировать в жестко закодированное значение, вы должны написать свой собственный c'tor по умолчанию:

class Something 
{ 
    int m_a; 

    // implement your own default c'tor 
    Something() : m_a(0) {} 
}; 
Смежные вопросы