const против неконстантных встроенных переменных - PullRequest
1 голос
/ 10 апреля 2020

Предположим, у меня есть следующие два файла:

test.cpp

inline double pi { 3.1415 };
#include <iostream>

void test() {

    std::cout << pi << std::endl;

}

и

main.cpp

inline double pi { 2.178 };

void test();

#include <iostream>

int main() {

    std::cout << pi << std::endl;
    test();

}

inline переменные по умолчанию имеют внешнюю связь. Итак, моя первоначальная мысль, согласно правилу единого определения (ODR), заключается в том, что одна и та же переменная может быть объявлена ​​в нескольких единицах перевода, если переменная объявлена ​​как встроенная и содержит такое же точное определение

Итак, мой первый вопрос: почему эта программа компилируется, если, хотя переменные объявлены как встроенные, они имеют разные определения в единицах перевода?

Во-вторых, в чем разница между встроенными не const и встроенная переменная const?

Например, если вы запустите приведенный выше код, вы должны получить следующий вывод

2.178
2.178

Однако, если вы go для обоих файлов и делаете pi a const double, то есть inline const double pi {3.1415} и inline const double pi {2.178}

Вы получите следующий вывод:

2.178
3.1415

Что именно здесь происходит?

1 Ответ

2 голосов
/ 10 апреля 2020

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

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

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

Добавление const может привести к тому, что компилятор ( не компоновщик) в некоторых местах удалит «ссылки» на эту переменную, буквально «вставляя» значение инициализатора в точку использовать, как оптимизацию. Он может сделать это, когда узнает, что значение не изменится после инициализации (благодаря const). В результате вы больше не наблюдаете столько странностей из-за своего неопределенного поведения, потому что поведение, которое вы видите из своей программы, более ограничено отдельными единицами перевода.

...