2015-04-21 5 views
13

Я знаю, что для функции это просто будет встраиваемой:Не может ли компилятор определить, является ли переменная const самой?

int foo(int a, int b){ 
    return a + b; 
} 

Но мой вопрос, не может компилятор просто автоматически определит, что это то же самое, как:

int foo(const int a, const int b){ 
    return a + b; 
} 

И так как это может быть обнаружено, зачем мне нужно вводить const? Я знаю, что ключевое слово inline устарело из-за прогресса компилятора. Разве не время, что const сделать то же самое?

+0

Точка 'const' предназначена для предотвращения того, что вы ошибочно измените значение. При чтении длинной функции, если вы видите 'const int x' в начале, вы знаете, что в строке 300' x' остается неизменной даже без проверки предыдущего кода. – chi

+16

Вы не набираете 'const' для компилятора, так как вы вводите его для себя. Вы говорите компилятору, чтобы пинать вас, если вы когда-либо попытаетесь изменить его значение. – Galik

+4

Ваш пример не очень хороший. В этом конкретном случае, когда компилятор опускает это в форму SSA, он увидит, что 'a' и' b' не назначены и не являются «энергонезависимыми», поэтому они эффективно «const» и действуют соответственно. 'const' намного эффективнее, когда он применяется к _pointers_ или является частью интерфейса функции (его подпись), так как тогда компилятор может полагаться на обещания функции для оптимизации. –

ответ

12

Да, компилятор может доказать свою силу в вашем примере.

Нет, это было бы бесполезно :-). (http://www.gotw.ca/gotw/081.htm). Реферат:

  • const помогает большинству, делая компилятор и компоновщик, выбирает функции для объектов const, включая функции const-члена, которые могут быть закодированы, чтобы быть более эффективными.
  • const не помогает с обычной моделью перевода (отличается от того, что я предполагал); компилятор должен увидеть всю программу для проверки фактической консистенции (которую простая декларация не гарантирует) и ее использования, а также доказать отсутствие наложения псевдонимов ...
  • ...и , когда компилятор может видеть всю программу и может доказать фактическую константу, она, конечно, не нуждается в объявлении const больше! Это может доказать это. Duh.
  • Одно место, где const имеет большое значение, - это определение , поскольку компилятор может хранить объект в постоянной памяти.

Статья, конечно, стоит прочитать.

Что касается всей оптимизации/перевода программы, которая обычно необходима для использования константы ср. комментарии ниже от amdn и Angew.

+0

Прибывшие интегрированные «компиляторы», и не являются необычными :-) https://gcc.gnu.org/onlinedocs/gccint/LTO-Overview.html – amdn

+1

@amdn Спасибо за информацию. Интегрировал его в свой ответ. –

+0

Цепь VS также имеет LTCG (генерация кода времени). Я бы сказал, что большинство (если не все) современных компиляторов делают. – Angew

9

не может компилятор просто автоматически определит, что это то же самое, как ...

Если с тем, что вы имеете в виду, может ли компилятор обнаружить, что переменные не изменяются во втором случае , скорее всего, да. Компилятор, вероятно, будет производить одинаковый вывод для обоих образцов кода. Однако const может помочь компилятору в более сложных ситуациях. Но самое главное, что он вас из-за непреднамеренно модифицирования одной из переменных.

+1

Возможно ли, что вы могли бы объяснить, какая ситуация была бы там, где компилятор не смог бы обнаружить, что переменная является 'const'? Я понял, что вы изменили это с помощью «сложных ситуаций». Так что, возможно, слишком сложно идентифицировать такое событие, я просто надеялся увидеть что-то из первых рук. –

+4

@JonathanMee Скорее всего разные единицы перевода. Компилятор в модели компилятора C/C++ (в отличие, например, от модели C#) не имеет доступа к объектным файлам, даже если они содержат достаточную информацию о типе. Он не может знать, что функция в другом TU не изменяет параметр, переданный ref или указателем. (Линкером было бы, но потом уже слишком поздно для генерации кода, если у вас не будет выполнения нескольких компиляции/ссылок, как с информацией об оптимизации времени выполнения, или необычным интегрированным «компилятором»). –

+2

@PeterSchneider Это на самом деле лучший ответ, который я видел до сих пор. Я хотел бы принять это, если бы вы могли набрать его в качестве ответа, сэр. –

3

Возможно, он мог бы, но const заявление также для вы. Если вы установите переменную как const и попытаетесь присвоить новое значение, вы получите сообщение об ошибке. Если бы компилятор сам выдал var, это не сработало бы.

18

Вы не ставите const в результате изменения переменной. Вы используете const до , применяя, вы его не изменяете. Без const вы можете изменить значение. С const компилятор будет жаловаться.

Это вопрос семантики. Если значение не должно быть изменчивым, используйте const, и компилятор выполнит это намерение.

+0

Итак, нет никакого выигрыша от команды 'const'? Забавно, я думал, что есть ... –

+2

Я удалил свой последний комментарий; Думаю, я лучше знаю, где ты собираешься с этим. Тот факт, что компилятор может принудительно использовать 'const', также является доказательством того, что он может сделать ту же оптимизацию, независимо от того, указан ли вы' const'. Я бы предположил, что большинство компиляторов, таким образом, генерируют точно такой же код для указанных 'const' и не указанных -const'-but-not-modified-anyway. – tenfour

+0

Правильно поэтому я ссылался на 'inline', что компилятор будет' inline' функциями по своему усмотрению, спрашиваем ли мы это. Я говорю то же самое для 'const'. Я никогда не объявляю функции 'inline' больше, потому что компилятор знает лучше, чем я. Почему я должен объявлять переменные 'const'? –

0

Короткий ответ: потому что не все проблемы такие простые.

Более длинный ответ: Вы не можете предположить, что подход, который работает с простой проблемой также работает со сложной проблемой

Точный ответ: Const это намерение. Основная цель const - предотвратить случайное выполнение вами каких-либо действий. Если компилятор автоматически добавит const, он просто увидит, что этот подход НЕ является const и оставляет его на нем. Использование ключевого слова const приведет к возникновению ошибки.

2

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

Переменная может быть действительно const (это означает, что она записывается в месте только для чтения, а значит, оптимизация компилятора), если она является константой во время ее объявления.

Вы можете предоставить свою вторую переменную non const, которая станет «const» внутри области функций.

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

Учитывая, что определители констант предназначены главным образом для обеспечения соблюдения кода, и что компиляторы будут генерировать тот же код в 99% случаев, если переменная является константой или не const, а затем NO, компилятор не должен автоматически определять константу.

+0

Это похоже на аргумент против 'auto'. Если код будет заканчиваться тем же, * то как const помогает что-нибудь? * Почему мы вообще пишем? –

+0

Const полезен для обеспечения исполнения кода. В небольшой функции, такой как это, это может показаться не большим выигрышем, однако в более широком контексте (например, в классах, имеющих функции const или принимающих константные paremeters), это дает возможность самостоятельной документации к коду (если функция принимает const, то создатель этой функции утверждает, что он не будет изменять эту переменную внутри). Что касается auto: это используется, чтобы избежать указания очевидного типа (EG: если функция возвращает пространство namespace1 :: namespace2 :: namespace3 :: ClassA, вы скорее просто скажете auto, а затем поместите все). – MichaelCMS

9

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

Что может сделать компилятор never Знаете ли вы, что вы хотели сделать.

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

Это ключевое слово const.

4
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 упрощает определенные оптимизации (что может сделать их возможным) и обеспечивает выполнение функций программиста (что помогает программисту) и может изменить код().

Смежные вопросы