Почему раздельное определение и инициализация переменных в C ++? - PullRequest
21 голосов
/ 23 марта 2011

В настоящее время я работаю над довольно старым кодом C ++ и часто нахожу такие вещи, как

int i;
i = 42;

или

Object* someObject = NULL;
someObject = new Object();

или даже

Object someObject;
someObject = getTheObject();

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

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

Интересно, должен ли я просто изменить код на

int i = 42;
Object* someObject = new Object();
Object someObject = getTheObject();

Может ли это привести к каким-либо проблемам?

Ответы [ 8 ]

16 голосов
/ 23 марта 2011
Object someObject;
someObject = getTheObject();

При этом используется оператор присваивания.

Object someObject = getTheObject();

При этом используется конструктор копирования.

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

8 голосов
/ 23 марта 2011

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

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

Однако в C ++ нет реальной причины делать это. Лучше всегда определяйте свои переменные, где вы можете инициализировать их напрямую.

6 голосов
/ 23 марта 2011

Изменение, которое вы предлагаете, настоятельно рекомендуется!Это часть важной идиомы в программировании на C ++, а именно Получение ресурсов - инициализация .

2 голосов
/ 23 марта 2011

Рассмотрим следующий случай:

SomeType object;
if( whateverCondition ) {
   object = getObjectOneWay();
} else {
   object = getObjectAnotherWay();
}

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

1 голос
/ 08 сентября 2012

На оборудовании, основанном на ПЗУ, есть хорошая техническая причина, это НЕ проблема стиля:

В встроенных системах на основе ROM / EEPROM это влияет на то, где в двоичном виде записывается значение. Неинициализированные переменные записываются в .bss, тогда как инициализированные переменные записываются в .data. Преждевременная инициализация приведет к переполнению пространства в ПЗУ, что в старых встроенных системах может привести к большим неприятностям. Если вы работаете в системе с небольшим ПЗУ, вам может не хватить памяти, если вы инициализируете без необходимости. Некоторые тупые компиляторы даже обращаются напрямую в ПЗУ, делая эти значения доступными только для чтения, если вы не будете осторожны.

например. Посмотрите этот пример GameBoy для более подробного объяснения: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_varinit

1 голос
/ 23 марта 2011

Зачем разделять определение и инициализацию переменных в C ++?

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

Object someObject;
someObject = getTheObject();

сильно отличается от Object someObject = getTheObject();

someObject = getTheObject(); вызывает оператор присваивания класса Object, тогда как в Object someObject = getTheObject(); вызывается конструктор копирования класса. Это также известно под именем копия инициализации

Хороший компилятор может генерировать тот же код в случае int i; i = 42; и int i =42. Там не будет много накладных расходов.

Кстати, я всегда предпочитаю от int i = 42 до int i; i=42 и

Object someObject = getTheObject(); до

Object someObject; someObject = getTheObject();

P.S: int i = 42 определяет и инициализирует i, тогда как int i; i=42 определяет i, а затем присваивает ему 42.

1 голос
/ 23 марта 2011
int i;
i = 42;

Это не отдельное определение переменной и инициализация .

Это отдельное объявление переменной и присваивание . Я не вижу причин для этого. Если вы знаете значение на момент объявления переменной, то инициализируйте его прямо тогда. Таким образом, ваш вопрос не имеет никакого объяснения.

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

0 голосов
/ 23 марта 2011

Нет. Это вопрос стиля.

Однако, если бы он когда-либо хотел убрать объявление из функции, было бы меньше редактирования, если объявление и инициализация разделены.

...