Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: Basil2 Россия https://starostin.msk.ru
Дата: 03.10.23 16:06
Оценка:
Есть код:

void DoLogging()
{
static const bool created = std::filesystem::create_directories(PathToLog);
...
}

Константа created нигде не используется. Конструкция с ней сделана только для того, чтобы не запариваться с once_flag/call_once для вызова create_directories(). Код получается лаконичнее и чище.

Однако, пришла мысль — ну как компилятор увидит, что константа не используется, и выкинет вызов create_directories()?

Вопрос — что о такой ситуации говорит Стандарт?

Я нашел немного про gcc:
"Static variables that are not used (or only written to), whose address is not taken or does not escape, are removed. Static functions that are called only once are inlined, those that are never called are never generated (unless you take pointers to them)."

Но хотелось бы узнать, что говорит на этот счет Стандарт.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Отредактировано 03.10.2023 16:10 Basil2 . Предыдущая версия . Еще …
Отредактировано 03.10.2023 16:09 Basil2 . Предыдущая версия .
Отредактировано 03.10.2023 16:08 Basil2 . Предыдущая версия .
Re: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: qaz77  
Дата: 03.10.23 17:01
Оценка: +1
Здравствуйте, Basil2, Вы писали:

B>Есть код:


B>
B>void DoLogging()
B>{
B>static const bool created = std::filesystem::create_directories(PathToLog);
B>...
B>}
B>


Вот я бы представил, что вызывается std::filesystem::create_directories(PathToLog) без всяких присваиваний переменным.
Компилятор как будет судить об отсутствии side effects?
Никак, тем более, что тут они очевидно (для программиста, а не компилятора) есть.
Re: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: reversecode google
Дата: 03.10.23 17:06
Оценка:
введите в гугле
call_once vs static
и почитайте
там много флуда на разных площадках, еще и видосики в ютубе
Re: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: watchmaker  
Дата: 03.10.23 23:17
Оценка:
Здравствуйте, Basil2, Вы писали:


B>Константа created нигде не используется. Конструкция с ней сделана только для того, чтобы не запариваться с once_flag/call_once для вызова create_directories(). Код получается лаконичнее и чище.


А как код компилируется без атрибута [[maybe_unused]] и без предупреждений? Надеюсь, это тут на форуме не написан атрибут, а не в компиляторе предупреждения выключены.

B>Вопрос — что о такой ситуации говорит Стандарт?


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

B>Я нашел немного про gcc:

B>"Static variables that are not used (or only written to), whose address is not taken or does not escape, are removed.

Если gcc выкинет переменную created, оставив защищающий её guard и первый вызов create_directories, то наблюдаемое поведение программы не изменится. Так что gcc так может делать и вправду делает. Такие действия gcc удовлетворяют требованиям языка C++.
Re[2]: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: Basil2 Россия https://starostin.msk.ru
Дата: 04.10.23 12:38
Оценка:
Здравствуйте, reversecode, Вы писали:

R>введите в гугле

R>call_once vs static
R>и почитайте
R>там много флуда на разных площадках, еще и видосики в ютубе

Вот именно, что флуда ((
Я почитал бегло, но вопрос выкинет или нет там не поднимается...
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[3]: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: reversecode google
Дата: 04.10.23 12:45
Оценка:
правильно
там поднимается вопрос что лучше
и зачем вообще изобрели call_once это есть чудесные статик переменные
тонко вам намекаю что не всяко статик лучше в целом чем обсуждение что там выкинет компиль
Re[2]: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: Basil2 Россия https://starostin.msk.ru
Дата: 04.10.23 12:54
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>А как код компилируется без атрибута [[maybe_unused]] и без предупреждений? Надеюсь, это тут на форуме не написан атрибут, а не в компиляторе предупреждения выключены.


Прекрасно компилируется безо всяких предупреждений. Атрибута нет. Visual Studio 2019 Version 16.11.26, уровень предупреждений /W4.

B>>Вопрос — что о такой ситуации говорит Стандарт?


W>Стандарт говорит, что компилятор вправе делать что угодно, если это не меняет наблюдаемое поведение программы.


Спасибо. То есть если у переменной нетривиальная инициализация, ее выкинуть не могут?

B>>Я нашел немного про gcc:

B>>"Static variables that are not used (or only written to), whose address is not taken or does not escape, are removed.

W>Если gcc выкинет переменную created, оставив защищающий её guard и первый вызов create_directories, то наблюдаемое поведение программы не изменится. Так что gcc так может делать и вправду делает. Такие действия gcc удовлетворяют требованиям языка C++.


Такое поведение меня вполне устроит. Только речь не о gcc ))
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[4]: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: Basil2 Россия https://starostin.msk.ru
Дата: 04.10.23 12:57
Оценка:
Здравствуйте, reversecode, Вы писали:

R>там поднимается вопрос что лучше


И лучше однозначно статик. И проще, и быстрее.

R>и зачем вообще изобрели call_once это есть чудесные статик переменные


Ради, например, нескольких функций.

R>тонко вам намекаю что не всяко статик лучше в целом чем обсуждение что там выкинет компиль


Не вкурил в фразу намек, если честно.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[3]: Выкинет ли оптимизатор код инициализации неиспользуемой пере
От: watchmaker  
Дата: 04.10.23 13:33
Оценка: 6 (1) +1
Здравствуйте, Basil2, Вы писали:


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


B>То есть если у переменной нетривиальная инициализация, ее выкинуть не могут?


Её — это про переменную или про инициализацию?

Переменную компилятору разрешено выкинуть (опять же, если она не используется потом).

Код инициализации компилятору разрешено выкинуть только если он заменит его другим кодом с таким же наблюдаемым поведением. То есть в данном случае это означает, что при каждом входе в функцию должна будет вызываться create_directories до тех пор, пока этот вызов не завершится без выбрасывания исключения.
Просто потому что у вызова create_directories есть как собственные наблюдаемые эффекты, так и поведение другого кода может всё равно видеть результат этого вызова (например, по наличию исключения filesystem_error, выброшенного из DoLogging) и также менять своё поведение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.