Может ли компилятор не определить, является ли переменная константной самой?
Я знаю, для функции это просто, это будет встроено:
int foo(int a, int b){
return a + b;
}
Но мой вопрос, не может ли компилятор просто определить, что это то же самое, что и:
int foo(const int a, const int b){
return a + b;
}
И поскольку это может быть обнаружено, зачем мне печатать const
в любом месте? Я знаю что inline
Ключевое слово устарело из-за достижений компилятора. Разве не пришло время const
делать то же самое?
8 ответов
Да, компилятор может доказать постоянство в вашем примере.
Нет, это было бы бесполезно:-).
Обновление: Херб Саттер посвятил одну из своих проблем этой теме ( http://www.gotw.ca/gotw/081.htm). Резюме:
- const помогает больше всего, заставляя компилятор и компоновщик выбирать функции для const-объектов, включая функции-члены const, которые можно кодировать для большей эффективности.
- const не помогает с обычной моделью модуля перевода [отличается от того, что я предполагал]; компилятор должен видеть всю программу для проверки фактической константности (которую не гарантирует простое объявление) и ее использования, а также доказать отсутствие псевдонимов...
- ... и когда компилятор может видеть всю программу и может доказать фактическую константность, ему, разумеется, больше не требуется объявление const! Это может доказать это. Duh.
- Единственное место, где const имеет большое значение, - это определение, потому что компилятор может хранить объект в постоянной памяти.
Статью, конечно, стоит прочитать.
Что касается оптимизации / перевода всей программы, которая обычно необходима для использования константности, см. комментарии ниже от amdn и Angew.
Ты не ставишь const
в результате не изменения переменной. Ты используешь const
чтобы заставить вас не изменять его. Без const
Вы можете изменить значение. С const
Компилятор пожалуется.
Это вопрос семантики. Если значение не должно быть изменяемым, используйте const
и компилятор осуществит это намерение.
Компилятор всегда будет знать, что вы сделали, и выведет из этого внутреннюю константность для оптимизации кода.
То, что компилятор не может знать, это то, что вы хотели сделать.
Если вы хотите, чтобы переменная оставалась постоянной, но случайно изменили ее позже в коде, компилятор может перехватить эту ошибку, только если вы сообщите компилятору, что вы хотели.
Это то, что const
Ключевое слово для.
не может компилятор просто автоматически определить, что это так же, как...
Если под этим вы подразумеваете, может ли компилятор обнаружить, что переменные не изменены во втором случае, скорее всего, да. Компилятор, скорее всего, выдаст одинаковый вывод для обоих примеров кода. Тем не мение, const
может помочь компилятору в более сложных ситуациях. Но самый важный момент заключается в том, что он не позволяет случайно изменить одну из переменных.
struct bar {
const int* x;
};
bar make_bar(const int& x){
return {&x};
}
std::map<int,bar> data;
shuffle(data);
знаю это bar
никогда не изменится x
(или вызвать его изменение) в его жизни требует понимания каждого использования bar
в программе, или, скажем, делая x
указатель на const
,
Даже при совершенной оптимизации всей программы (которая не может существовать: машины Тьюринга не совсем понятны), динамическое связывание означает, что вы не можете знать во время компиляции, как будут использоваться данные. const
является обещанием, и нарушение этого обещания (в определенных контекстах) может быть UB. Компилятор может использовать этот UB для оптимизации таким образом, чтобы игнорировать нарушение обещания.
inline
не устарел: это означает то же самое, что он когда-либо делал, что конфликты линкера этого символа должны игнорироваться, и он мягко предлагает внедрить код в вызывающую область.
const
упрощает некоторые оптимизации (которые могут сделать их возможными) и навязывает вещи программисту (что помогает программисту), и может изменить то, что означает код (const
перегрузки).
Может быть, он мог, но константное утверждение также для вас. Если вы установите переменную как const и попытаетесь присвоить новое значение впоследствии, вы получите ошибку. Если компилятор сам сделает из него переменную, это не сработает.
Спецификатор const - это метод для обеспечения поведения переменных внутри вашей области видимости. Он предоставляет компилятору только средства кричать на вас, если вы пытаетесь изменить их внутри области, где они объявлены как const.
Переменная может быть действительно const (то есть она записана в месте, доступном только для чтения, следовательно, оптимизируется компилятор), если она const во время ее объявления.
Вы можете предоставить 2-й функции неконстантные переменные, которые станут "константными" внутри области действия функции.
Или же вы можете обойти const путем приведения, так что компилятор не может проанализировать весь ваш код в попытке выяснить, будет ли изменено значение а или нет внутри области действия функции.
Учитывая, что квалификаторы const предназначены главным образом для принудительного применения кода, и что компиляторы будут генерировать один и тот же код в 99% случаев, если переменная является константной или неконстантной, то НЕТ, компилятор не должен автоматически определять константность.
Короткий ответ: потому что не все проблемы настолько просты.
Более длинный ответ: Вы не можете предполагать, что подход, который работает с простой проблемой, также работает со сложной проблемой
Точный ответ: const - это намерение. Основная цель const - предотвратить случайные действия. Если компилятор добавит const автоматически, он просто увидит, что подход НЕ является const, и оставит его на нем. Использование ключевого слова const вместо этого вызовет ошибку.