Запрет на произвольный порядок записи инициализаторов в списках инициализации в конструкторах.

Никита Колотов
Никита Колотов

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

15.6.2 [class.base.init] 13 In a non-delegating constructor, initialization proceeds in the following order:
(13.1) First, and only for the constructor of the most derived class (6.6.2), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
(13.2) Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list
(regardless of the order of the mem-initializers).
(13.3) Then, non-static data members are initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).

На практике это может приводить ко следующим проблемам:

1. Неопределенное Поведение непосредственно из-за использования неинициализированных полей:

struct foo
{
    foo(void)
    : frob{42}
    , zig{frob * 2} // frob is uninitialized at this point
    {}

    int zig;
    int frob;
};

2. промахи с порядком вызова функций с побочными эффектами, используемых при инициализации:

int first(void);
int second(void);

struct foo
{
    foo(void)
    : frob{first()}
    , zig{second()} // second is called prior to first
    {}

    int zig;
    int frob;
};

В современных компиляторах уже достаточно давно реализованы диагностические сообщения на такой случай (-Wreorder). Соответственно я предлагаю добавить в стандарт требование однозначного соответствия следования инициализаторов в списке инициализации реальному порядку их вызова.

14
рейтинг
5 комментариев
zamazan4ik@tut.by

У Вас есть какие-то оценки о том, сколько кода сломается? :)

zamazan4ik@tut.by
Никита Колотов

zamazan4ik@tut.by, Не так много. По большей части сломается только уже сломанный, неподдерживаемый код, в первую очередь старые проекты под Visual Studuo, в которой до недавнего времени диагностика такого рода проблем ограничивалась обнаружением использования неинициализированных переменных. Проекты под g++ и clang++ собираемые хотя бы с минимальным уровнем предупреждений -Wall (в который входит -Wreorder) по идее не должны потребовать правок. Осознание сложностей с неправильным порядком инициализаторов пришло достаточно давно - диагностика Wreorder появилась более 10 лет назад, так что данное предложение по сути просто попытка закрепить устоявшуюся практику.

Никита Колотов
Alexander

Никита Колотов, я это понимаю. Но навскиду и я могу говорить. Я более чем уверен, что есть куча кодовой базы, которая собирается без этого варнинга\забивает на него. Поэтому это может отломать работающий нормально код.

Если приведёте статистику, которую вы соберёте хотя бы по Open Source проектам, к своему предложению, будет превосходно. Если что, могу дать отправную точку, как это делать :)

Alexander
Никита Колотов

Alexander, Скажем так, проекты, которые не задают при сборке даже минимального уровня предупреждений (то бишь даже без -Wall), я бы не стал характеризовать как "работающий нормально код". Статистику собрать было бы конечно хорошо, но как собрать достаточно объемную достоверную статистику - это вопрос. Первое, что приходит в голову - поискать на гитхабе: поиск [c++] -Wall дает 11М+ результатов по коду 1M по коммитам, а -Wno-reorder только 36К по коду и только 625 коммитов.

Никита Колотов
Обновлено 
webreh

Для начало надо это deprecate, и никакой код не сломается.

webreh
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения