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

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

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

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

02.02.2013, 18:15. Просмотров 636. Ответов 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) {}; Зачем
Посмотрите здесь:

Какое число вернет foo(5)? - C++
int foo (int n) { if (n <= 0) return 0; return foo (n - 2) + foo (n / 2) + 1; } Вставляю код, выполняю с нужным...

Задачка: какое значение вернет foo(7)? - C++
Как решаются такие рода задачки, подскажите пожалуйста. int foo(int n) { if(n<=0) return 1; else return...

Обеспечить вызов функции foo в x% случаев - C++
Добрый день! Возникла следующая трудность. Есть функции void increment() и void decrement(). Есть цикл до 100, в котором...

Отметьте все верные утверждения относительно вызова функции foo - C++
Есть три версии функции foo: void foo(char) { std::cout << "char" << std::endl; } void foo(signed char) { std::cout << "signed char"...

Где может быть использована сигнатура int& foo()=7 - C++
Друзья, это чисто теоретический вопрос. Подскажите где может быть использована такая функция. Какой в этом практический смысл? ...

Копировать значение поля m_moo в значение поля m_moo класса foo - C++
А что означает запись? Foo1(Foo1 const& foo):m_moo(foo.moo) то что это к.копирования понятно.Не понятно,зачем список инициализации.... ...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1608 / 1000 / 118
Регистрация: 27.09.2009
Сообщений: 1,931
Завершенные тесты: 1
02.02.2013, 18:19     Foo::foo(): x(dx), y(dy) {}; Зачем #2
Стандартное - первое (называется списком инициализации). Преимущества в том, что члены, перечисленные в списке инициализации, именно инициализируются указанными значениями. Во втором случае они сначала инициализируются по умолчанию, а потом им уже в теле присваивается новое значение. Для численных типов разница незначительна, а вот для сложных объектов это может уже сказаться основательно. Что ещё более важно, если член не имеет конструктора по умолчанию, то единственный способ его инициализировать - список инициализации. Это относится и к членам, имеющим тип "ссылка".
Vourhey
Почетный модератор
6477 / 2252 / 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
Эксперт С++
1608 / 1000 / 118
Регистрация: 27.09.2009
Сообщений: 1,931
Завершенные тесты: 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
Каратель
Эксперт С++
6553 / 3973 / 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
Эксперт С++
1608 / 1000 / 118
Регистрация: 27.09.2009
Сообщений: 1,931
Завершенные тесты: 1
02.02.2013, 18:53     Foo::foo(): x(dx), y(dy) {}; Зачем #8
По умолчанию встроенные числовые типы имеют неопределённое значение. Под "неопределённым значением" в данном контексте понимается, что там может оказаться какое угодно число, как повезёт. Так что при конструировании Foo по умолчанию вся процедура сведётся к вызову конструктора по умолчанию для string. Если надо, чтобы при конструировании Foo по умолчанию член id принимал определённое значение, пишем соответствующий конструктор с сигнатурой Foo::Foo() и упоминаем id в списке инициализации.
MrGluck
Модератор
Эксперт CЭксперт С++
7183 / 4349 / 634
Регистрация: 29.11.2010
Сообщений: 11,840
02.02.2013, 19:38     Foo::foo(): x(dx), y(dy) {}; Зачем #9
При использовании списка инициализации для членов вызывается конструктор копирования, объекты конструируются заранее со значениями, переданными им. Если этого не происходит, то сначала вызывается конструктор по-умолчанию, а далее вызывается оператор присвоений. Не говоря о том, что это логически не совсем то, чего мы хотели, это еще и лишние операции. Вдобавок, ссылки и константные члены обязаны быть проинициализированны на момент объявления.
За сим список инициализации стоит использовать всегда, за одним редким исключением, когда требуется множественное присваивание.
diagon
Higher
1928 / 1194 / 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
1482 / 1058 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
02.02.2013, 20:08     Foo::foo(): x(dx), y(dy) {}; Зачем #12
работает так, как и должен работать. то, что при инициализации вызывается метод, который обращается к еще неинициализированному мемберу - это не вина списка инициализации, что в этой ссылке и написано. так можно и без всяких потоков написать.
diagon
Higher
1928 / 1194 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
02.02.2013, 20:33     Foo::foo(): x(dx), y(dy) {}; Зачем #13
Цитата Сообщение от DU Посмотреть сообщение
так можно и без всяких потоков написать.
Ну, тогда оно просто не будет работать. В случае с потоками оно всего лишь иногда не работает, что еще веселее.

Цитата Сообщение от DU Посмотреть сообщение
это не вина списка инициализации
Вина списка инициализации в том, что он инициализирует мемберы не в том порядке, в котором они перечислены в списке.
В целях рефакторинга поменял переменные местами - программа перестала работать. Нет уж, пусть такая ситуация остается в анекдотах.
Хотя, соглашусь, это некритично. Для меня наиболее важно то, что
Цитата Сообщение от diagon Посмотреть сообщение
у него некошерный синтаксис
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
02.02.2013, 20:47     Foo::foo(): x(dx), y(dy) {}; Зачем #14
Цитата Сообщение от diagon Посмотреть сообщение
Вина списка инициализации в том, что он инициализирует мемберы не в том порядке, в котором они перечислены в списке.
вот как раз тут все логично, это вина программиста, который не знает язык или пишет код в не в здравом уме
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.02.2013, 23:52     Foo::foo(): x(dx), y(dy) {}; Зачем
Еще ссылки по теме:

Зачем? - C++
#include <cstdlib> #include <iostream> #include <time.h> #include <math.h> #include <vector> #define ABS(x) (x < 0) ?...

зачем? - C++
зачем для создания динамических переменных, мы должны прописывать их тип дважды? прим: float * a_pps = new float; double * ex = new...

Зачем :: - C++
LRESULT CALLBACK WndProc(HWND windowHandle, UINT msg, WPARAM wParam, ...

Зачем int ? - C++
Зачем многие присваивают функции тип int, когда это не требуется ? Например: Зачем делать так, #include <iostream> using namespace...


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

Или воспользуйтесь поиском по форуму:
MrGluck
Модератор
Эксперт CЭксперт С++
7183 / 4349 / 634
Регистрация: 29.11.2010
Сообщений: 11,840
02.02.2013, 23:52     Foo::foo(): x(dx), y(dy) {}; Зачем #15
Цитата Сообщение от diagon Посмотреть сообщение
компайлер это должен соптимизировать(но проверять лень).
думаю это справедливо лишь для POD типов

Список инициализации не виноват в проблемах навроде того, что перечисляют не в том порядке, в каком объявляют в классе, или, если рассматривать проблему в общем случае, используют обращение к неинициализированным переменным.
Yandex
Объявления
02.02.2013, 23:52     Foo::foo(): x(dx), y(dy) {}; Зачем
Ответ Создать тему
Опции темы

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