Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.93/29: Рейтинг темы: голосов - 29, средняя оценка - 4.93
275 / 152 / 52
Регистрация: 30.06.2011
Сообщений: 1,700
1

Инициализация полей класса

25.09.2017, 19:24. Просмотров 6015. Ответов 18
Метки нет (Все метки)


Приветствую всех. Не в одной книге по С++ сказано, что поля класса желательно инициализировать в списке инициализации конструктора этого класса. В противном случае, а именно в случае инициализации поля в теле конструктора, поле сначала будет инициализировано нулем, а потом ему присвоится значение в теле конструктора, то есть двойная работа. Решив это проверить я написал такой код:
C++
1
2
3
4
5
6
7
8
class A
{
 private:
 int x;
 
 public:
 A() { std::cout << x; x = 7; }
};
Выполнив код на этом сайте, все подтвердилось: x в теле конструктора инициализирован нулем. Далее я запустил RAD Studio 10.1, создал консольное приложение и выполнил этот же код. В результате увидел, что x перед сохранением в нем числа 7 хранит не 0. Почему так происходит? Компилятор отступает от стандарта?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.09.2017, 19:24
Ответы с готовыми решениями:

Инициализация полей класса при наследовании
Всем добрый вечер. Возникла у меня небольшая задачка, которую никак не могу решить. Имеем базовый...

Инициализация полей класса через vector<>
Здравствуйте, можете подсказать как правильно инициализировать поля класса, вот например есть класс...

Инициализация полей во время объявления класса
Инициализировать поля класса во время его объявления возможно только если в классе отсутствует...

Инициализация вещественных статических константных полей класса С++
static const double x=2.15; //c double и float не инициализирует. Почему??

18
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
25.09.2017, 19:30 2
d7d1cd, а почему Вы решили, что оно должно инициализироваться нулем?
0
275 / 152 / 52
Регистрация: 30.06.2011
Сообщений: 1,700
25.09.2017, 19:44  [ТС] 3
Цитата Сообщение от Croessmah Посмотреть сообщение
d7d1cd, а почему Вы решили, что оно должно инициализироваться нулем?
Это не я решил. Это так в книге написано: Джефф Элджер Библиотека программиста, 34-35 страница:
Кликните здесь для просмотра всего текста
Списки инициализации членов
Чтобы избавиться от этой проблемы, в C++ находится очередное применение символу : — для создания списков
инициализации членов. Так называется список спецификаций конструкторов, разделенных занятыми и расположенных между сигнатурой конструктора и его телом.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo {
public:
 Foo(char*);
};
class Bar : public Foo {
public:
 Bar(char*);
};
class BarBar {
private:
 Foo f;
 int x;
public:
 BarBar();
};
Bar::Bar(char* s) : Foo(s) {...}
BarBar::BarBar : f(“Hello”), x(17) {...}
В конструкторе Bar список инициализации членов используется для инициализации базового класса Foo. Компилятор выбирает используемый конструктор на основании сигнатуры, определяемой по фактическим аргументам. При отсутствии списка инициализации членов сконструировать Bar было бы невозможно, поскольку компилятор не мог бы определить, какое значение должно передаваться конструктору базового класса Foo. В конструкторе BarBar список инициализации членов использовался для инициализации (то есть вызова конструкторов) переменных f и х. В следующем варианте конструктор работает не столь эффективно (если только компилятор не отличается сверхъестественным интеллектом):
C++
1
2
3
4
BarBar::BarBar() : f(“Hello”)
{
 x = 17;
}
Во втором варианте переменная х сначала инициализируется значением 0 (стандартное требование C++) с использованием по умолчанию конструктора int без аргументов, а затем в теле конструктора ей присваивается значение 17. В первом варианте имеется всего одна инициализация и потому экономится один-два машинных такта. В данном примере это несущественно, поскольку переменная х — целая, но если бы она относилась к более сложному классу с конструктором без аргументов и перегруженным оператором присваивания, то разница была бы вполне ощутима.
0
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
25.09.2017, 20:14 4
Это еще может зависеть от способа инициализации объекта.


http://en.cppreference.com/w/c... ta_members
0
1365 / 588 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
25.09.2017, 23:47 5
Цитата Сообщение от d7d1cd Посмотреть сообщение
Во втором варианте переменная х сначала инициализируется значением 0 (стандартное требование C++) с использованием по умолчанию конструктора int без аргументов
Не нулём. Это ошибка, относительно стандартного требования к конструктору int без параметров. Нет такого требования.

А вот то, что этот код даёт неочевидный результат, это мне, например, интересно.
Почему на сайте один порядок работы конструктора: конструкторский cout выводит значение, полученное из конструктора int (ещё не изменённое значение копированием), - а в clang, например, конструкторский cout даёт уже изменённое копированием значение?
0
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
25.09.2017, 23:53 6
daslex, не понял, о чем Вы? Примеры можно?
0
daslex
25.09.2017, 23:53
  #7

Не по теме:

ред

0
Croessmah
25.09.2017, 23:53
  #8

Не по теме:

Цитата Сообщение от daslex Посмотреть сообщение
ред
поз :D

0
1365 / 588 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
25.09.2017, 23:59 9
В смысле примеры. Подождите немного, сделаю скрины. Так наглядно будет.
0
Миниатюры
Инициализация полей класса   Инициализация полей класса  
daslex
26.09.2017, 00:12
  #10

Не по теме:

"ред". я пишу, если время на поправку вышло, но шанс исправить неточности есть, когда никто ничего написать не успел, можно исправить опечатки даже после 5 мин. Вы своей просьбой лишили меня надежды. Скринов два. Они выложены, если что. Мало ли отчёта ждёте, что готово.

0
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
26.09.2017, 00:17 11
daslex, при сборке clang и правда выводит 7.
http://rextester.com/UXD76586
С volatile int x; выводит 0.
0
1365 / 588 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
26.09.2017, 00:21 12
Вопрос автор темы задал неверно, но он хотел узнать то, что я показал. Неверно спросил из-за плохого перевода книги скорее всего, а то, что именно об этом хочет узнать, по-моему сейчас очевидно. Я тоже хочу об этом узнать.
0
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
26.09.2017, 00:33 13
daslex, использование не инициализированных переменных - undefined behavior (точную формулировку в стандарте нужно посмотреть).
А с UB компилятор может делать всё что угодно. А clang - вообще монстр в этом деле, так что я не удивлен.
Но за точными сведениями лучше залезть в стандарт. Это я так, отсебятины нагородил.
0
1365 / 588 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
26.09.2017, 00:44 14
Зато в vc++ volatile шлётся лесом, ноль не даёт.

Добавлено через 8 минут
Стандарт языка не накладывает никаких ограничений на возможные действия в конструкторе, так что можно написать целую содержательную программу внутри конструктора. Но это дурной стиль! Никогда не делайте ничего содержательного в конструкторе, ограничивайтесь только начальной инициализацией.
http://mech.math.msu.su/~vvb/2course/Lect01.html

Вот и всё. А пример вот он, прям в этой теме.
0
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
26.09.2017, 00:45 15
daslex, ноль и не обязателен.
В данном случае x будет содержать мусор.
Так что что ноль, что 7, что -2366661 - это всё мусор при выводе в cout.
2
1365 / 588 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
26.09.2017, 00:49 16
Я знаю, что необязателен. Просто Вы так выразились сначала, что можно будет подумать, что volatile спасает. Поэтому я написал, что написал.

Добавлено через 1 минуту
В clang это не мусор, а исключительно подкланговская фишка. Неспецифицированное поведение (Unspecified behavior).
0
Don't worry, be happy
16971 / 9852 / 1897
Регистрация: 27.09.2012
Сообщений: 24,429
Записей в блоге: 1
26.09.2017, 00:49 17
daslex, не, это я просто немного знаком с оптимизациями clang при ub.
http://rextester.com/SIW46957
1
1365 / 588 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
26.09.2017, 01:15 18
Убедили. Мусор. Оптимизаторы шалуны.
0
Mournful Max
26.09.2017, 02:28     Инициализация полей класса
  #19

Не по теме:

Croessmah, видели бы Вы мое лицо...) Нормальная такая оптимизация)))

0
26.09.2017, 02:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2017, 02:28
Привет! Вот еще темы с ответами:

Инициализация шаблонного класса(В конструкторе класса после двоеточия вновь имя класса)
Всем доброго времени суток! Пытаюсь разобраться как работает приведенный мной код. Конкретно,...

Создать класс CheckerBoard (особенности строения класса - инициализация константных членов класса)
Вот код: #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; const int xSize = 1;...

Инициализация экземпляра класса, как поле другого класса
Всем доброго времени суток ! Есть класс: class a{ public: a(int _type): type(_type) {} ...

Инициализация членов дочернего класса членами класса родителя
Есть уже созданный класс-родитель A. Как эффективно инициализировать дочерний класс B членами...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

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