Подтвердить что ты не робот

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

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

int i;
i = 42;

или

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

или даже

Object someObject;
someObject = getTheObject();

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

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

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

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

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

4b9b3361

Ответ 1

Object someObject;
someObject = getTheObject();

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

Object someObject = getTheObject();

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

Кроме того, ваши предложенные изменения эквивалентны, и вы должны их реализовать. Ожидается, что разность операторов копирования/оператора оператора приведет к такому же результату, однако этот язык не применяется на языке.

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

int i;
i = 42;

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

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

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

Ответ 6

Почему разделение переменной и инициализация в С++?

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

Object someObject;
someObject = getTheObject();

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

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

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

BTW Я всегда предпочитаю 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.

Ответ 7

Существует хорошая техническая причина для аппаратного обеспечения на базе ROM, это НЕ проблема стиля:

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

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

Ответ 8

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

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