Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
vbloodv
22 / 22 / 0
Регистрация: 15.12.2012
Сообщений: 314
#1

Foo::foo(): x(dx), y(dy) {}; Зачем - C++

02.02.2013, 18:15. Просмотров 609. Ответов 15
Метки нет (Все метки)

Очень часто видел конструктор типа
C++
1
Foo::foo(): x(dx), y(dy) {};
Сам использовал только в инициализации структур. Какие отличия от стандартного
C++
1
2
3
4
5
Foo:foo(int dx, int dy)
{
    x = dx;
    y = dy;
}
Что предпочтительнее, какие преимущества у конструкции первого типа?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.02.2013, 18:15     Foo::foo(): x(dx), y(dy) {}; Зачем
Посмотрите здесь:

C++ зачем?
C++ Зачем ::
Копировать значение поля m_moo в значение поля m_moo класса foo C++
Зачем int ? C++
Зачем? C++
C++ Какое число вернет foo(5)?
C++ Зачем false?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1602 / 994 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
02.02.2013, 18:19     Foo::foo(): x(dx), y(dy) {}; Зачем #2
Стандартное - первое (называется списком инициализации). Преимущества в том, что члены, перечисленные в списке инициализации, именно инициализируются указанными значениями. Во втором случае они сначала инициализируются по умолчанию, а потом им уже в теле присваивается новое значение. Для численных типов разница незначительна, а вот для сложных объектов это может уже сказаться основательно. Что ещё более важно, если член не имеет конструктора по умолчанию, то единственный способ его инициализировать - список инициализации. Это относится и к членам, имеющим тип "ссылка".
Vourhey
Почетный модератор
6473 / 2248 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
02.02.2013, 18:21     Foo::foo(): x(dx), y(dy) {}; Зачем #3
vbloodv, вызываются сразу конструкторы членов с параметрами. Во втором сначала контрукторы членов без параметров. Потом присваиваивание в теле конструктора класса.
Цитата Сообщение от vbloodv Посмотреть сообщение
Что предпочтительнее, какие преимущества у конструкции первого типа?
Думаю, сам поймешь.
vbloodv
22 / 22 / 0
Регистрация: 15.12.2012
Сообщений: 314
02.02.2013, 18:24  [ТС]     Foo::foo(): x(dx), y(dy) {}; Зачем #4
Цитата Сообщение от Nick Alte Посмотреть сообщение
Что ещё более важно, если член не имеет конструктора по умолчанию, то единственный способ его инициализировать - список инициализации.
Немножко не понимаю это момент, если член не имеет конструктора и единственный способ его проинициализировать это через список, т.е для доступа к констуктару нет возможности(к примеру такой член находится в статической библиотеке), но тогда как узнать какие поля класса можно инициализировать через список инициализации ?

Добавлено через 17 секунд
Цитата Сообщение от Vourhey Посмотреть сообщение
Думаю, сам поймешь.
Уже понял
Nick Alte
Эксперт С++
1602 / 994 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
02.02.2013, 18:28     Foo::foo(): x(dx), y(dy) {}; Зачем #5
Цитата Сообщение от vbloodv Посмотреть сообщение
если член не имеет конструктора
То его в принципе невозможно создать.
Член не может находиться в статической библиотеке, он находится в классе - то есть, в составе объектов этого класса. Если конструктор находится в статической библиотеке, то это вовсе не значит, что к нему нет доступа. Он описан в заголовочном файле, компилятор знает, как его вызывать - этого достаточно.

Цитата Сообщение от vbloodv Посмотреть сообщение
как узнать какие поля класса можно инициализировать через список инициализации
Очень просто - можно инициализировать все. Не включать в список можно только те, которые могут конструироваться по умолчанию, если нужно, чтобы именно по умолчанию они инициализировались.
vbloodv
22 / 22 / 0
Регистрация: 15.12.2012
Сообщений: 314
02.02.2013, 18:34  [ТС]     Foo::foo(): x(dx), y(dy) {}; Зачем #6
Цитата Сообщение от Nick Alte Посмотреть сообщение
Очень просто - можно инициализировать все.
C++
1
2
3
4
5
6
7
8
class Foo // псевдокод
{
int id;
string name;
int range;
int ability;
float rating;
}
Как будет происходить инициализация такого класса? Если значение переменной id нужно проинициализировать по умолчанию?
Jupiter
Каратель
Эксперт C++
6549 / 3969 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
02.02.2013, 18:52     Foo::foo(): x(dx), y(dy) {}; Зачем #7
Цитата Сообщение от vbloodv Посмотреть сообщение
Как будет происходить инициализация такого класса? Если значение переменной id нужно проинициализировать по умолчанию?
id иницализируется мусором
для name - вызван конструктор без параметров
в остальных полях - мусор

порядок инициализации соотвествует порядку объявления переменных в классе
если написать так
C++
1
2
3
Foo::Foo() : id()
{
}
то в id будет 0, для name вызовется конструктор без параметров, в оставшихся полях - мусор.
Nick Alte
Эксперт С++
1602 / 994 / 118
Регистрация: 27.09.2009
Сообщений: 1,918
Завершенные тесты: 1
02.02.2013, 18:53     Foo::foo(): x(dx), y(dy) {}; Зачем #8
По умолчанию встроенные числовые типы имеют неопределённое значение. Под "неопределённым значением" в данном контексте понимается, что там может оказаться какое угодно число, как повезёт. Так что при конструировании Foo по умолчанию вся процедура сведётся к вызову конструктора по умолчанию для string. Если надо, чтобы при конструировании Foo по умолчанию член id принимал определённое значение, пишем соответствующий конструктор с сигнатурой Foo::Foo() и упоминаем id в списке инициализации.
MrGluck
Ворчун
Эксперт CЭксперт С++
6327 / 3572 / 445
Регистрация: 29.11.2010
Сообщений: 9,456
02.02.2013, 19:38     Foo::foo(): x(dx), y(dy) {}; Зачем #9
При использовании списка инициализации для членов вызывается конструктор копирования, объекты конструируются заранее со значениями, переданными им. Если этого не происходит, то сначала вызывается конструктор по-умолчанию, а далее вызывается оператор присвоений. Не говоря о том, что это логически не совсем то, чего мы хотели, это еще и лишние операции. Вдобавок, ссылки и константные члены обязаны быть проинициализированны на момент объявления.
За сим список инициализации стоит использовать всегда, за одним редким исключением, когда требуется множественное присваивание.
diagon
Higher
1921 / 1187 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
02.02.2013, 19:50     Foo::foo(): x(dx), y(dy) {}; Зачем #10
Вот только работает список инициализации не всегда так, как это кажется на первый взгляд.
А это может привести к очень трудноуловимым ошибкам.
Ну и еще у него некошерный синтаксис.
Что касается начальной инициализации - компайлер это должен соптимизировать(но проверять лень).
Так что я все-таки предпочитаю обычную инициализацию, а после двоеточия пишу лишь вызов конструкторов.

Добавлено через 3 минуты
Цитата Сообщение от diagon Посмотреть сообщение
Вот только работает список инициализации не всегда так, как это кажется на первый взгляд.
А это может привести к очень трудноуловимым ошибкам.
Кривой, но пример.
Jupiter
02.02.2013, 20:03
  #11

Не по теме:

Цитата Сообщение от diagon Посмотреть сообщение
Кривой, но пример.
это уже слишком...

DU
1480 / 1056 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
02.02.2013, 20:08     Foo::foo(): x(dx), y(dy) {}; Зачем #12
работает так, как и должен работать. то, что при инициализации вызывается метод, который обращается к еще неинициализированному мемберу - это не вина списка инициализации, что в этой ссылке и написано. так можно и без всяких потоков написать.
diagon
Higher
1921 / 1187 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
02.02.2013, 20:33     Foo::foo(): x(dx), y(dy) {}; Зачем #13
Цитата Сообщение от DU Посмотреть сообщение
так можно и без всяких потоков написать.
Ну, тогда оно просто не будет работать. В случае с потоками оно всего лишь иногда не работает, что еще веселее.

Цитата Сообщение от DU Посмотреть сообщение
это не вина списка инициализации
Вина списка инициализации в том, что он инициализирует мемберы не в том порядке, в котором они перечислены в списке.
В целях рефакторинга поменял переменные местами - программа перестала работать. Нет уж, пусть такая ситуация остается в анекдотах.
Хотя, соглашусь, это некритично. Для меня наиболее важно то, что
Цитата Сообщение от diagon Посмотреть сообщение
у него некошерный синтаксис
Jupiter
Каратель
Эксперт C++
6549 / 3969 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
02.02.2013, 20:47     Foo::foo(): x(dx), y(dy) {}; Зачем #14
Цитата Сообщение от diagon Посмотреть сообщение
Вина списка инициализации в том, что он инициализирует мемберы не в том порядке, в котором они перечислены в списке.
вот как раз тут все логично, это вина программиста, который не знает язык или пишет код в не в здравом уме
MrGluck
Ворчун
Эксперт CЭксперт С++
6327 / 3572 / 445
Регистрация: 29.11.2010
Сообщений: 9,456
02.02.2013, 23:52     Foo::foo(): x(dx), y(dy) {}; Зачем #15
Цитата Сообщение от diagon Посмотреть сообщение
компайлер это должен соптимизировать(но проверять лень).
думаю это справедливо лишь для POD типов

Список инициализации не виноват в проблемах навроде того, что перечисляют не в том порядке, в каком объявляют в классе, или, если рассматривать проблему в общем случае, используют обращение к неинициализированным переменным.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.02.2013, 11:07     Foo::foo(): x(dx), y(dy) {}; Зачем
Еще ссылки по теме:

C++ Где может быть использована сигнатура int& foo()=7
C++ Зачем вычитать '0'
C++ Отметьте все верные утверждения относительно вызова функции foo
Задачка: какое значение вернет foo(7)? C++
C++ Обеспечить вызов функции foo в x% случаев

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
silent_1991
04.02.2013, 11:07     Foo::foo(): x(dx), y(dy) {}; Зачем
  #16

Не по теме:

Цитата Сообщение от diagon Посмотреть сообщение
Ну и еще у него некошерный синтаксис.
Хм, а мне наоборот нравится...

Yandex
Объявления
04.02.2013, 11:07     Foo::foo(): x(dx), y(dy) {}; Зачем
Ответ Создать тему
Опции темы

Текущее время: 07:40. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru