Может ли константная корректность улучшить производительность?

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

Следовательно, есть ли у вас примеры, когда корректность констант может помочь вашему компилятору улучшить производительность вашей программы?


person shuhalo    schedule 08.08.2010    source источник
comment
Постоянная корректность - одна из ЛУЧШИХ практик с точки зрения ремонтопригодности. Если ваш код C ++ не является корректным с точки зрения констант, это, по сути, куча дерьма в ожидании катастрофы. Это не должно влиять на производительность.   -  person    schedule 08.08.2010
comment
@ Нил Баттерворт: к сожалению, обратное неверно.   -  person Beta    schedule 08.08.2010
comment
Вот пример, когда const повлиял на производительность: stackoverflow.com / questions / 1121791 /. Однако по сути это была проблема качества реализации. const не определял, может компилятор на законных основаниях проводить оптимизацию, просто так случилось, что версия компилятора не смогла сделать это, когда она отсутствовала.   -  person Steve Jessop    schedule 08.08.2010
comment
Я совершенно уверен, что morgennebel пропустил «только» в первом предложении: это имеет гораздо больше смысла, поскольку это не только хорошая практика.   -  person IanH    schedule 08.08.2010
comment
@IanH Да, я думал об этом. Но у ОП было достаточно времени, чтобы прояснить ситуацию. Меня очень раздражают люди, которые задают вопросы, а потом просто исчезают.   -  person    schedule 08.08.2010
comment
Мартин, я думаю, вам не хватает «только» после «не», например, «не только хорошая практика».   -  person Catskul    schedule 02.07.2011


Ответы (4)


const правильность не может улучшить производительность, потому что const_cast и mutable находятся на языке и позволяют коду соответствующим образом нарушать правила. Это становится еще хуже в C ++ 11, где ваши const данные могут, например, быть указателем на std::atomic, что означает, что компилятор должен учитывать изменения, сделанные другими потоками.

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

При этом const правильность - это хорошо с точки зрения ремонтопригодности. В противном случае клиенты вашего класса могут сломать внутренние члены этого класса. Например, рассмотрим стандартный std::string::c_str() - если он не может вернуть константное значение, вы сможете поиграть с внутренним буфером строки!

Не используйте const по соображениям производительности. Используйте его из соображений ремонтопригодности.

person Billy ONeal    schedule 08.08.2010
comment
вы бы могли повозиться с внутренним буфером струны! - что очень важно, вы можете случайно испортить внутренний буфер. Ошибки компилятора из-за const - это указатели, говорящие о том, что вы делаете что-то глупое. - person Steve Jessop; 08.08.2010
comment
... а константные приведения - это указатели, говорящие, что автор этого кода пытается сделать что-то умное ;-) - person Steve Jessop; 08.08.2010
comment
@Steve Jessop - или const-cast - это указатели, говорящие, что я пытаюсь соединить константно-правильный код с неконстантно-правильным, и я не могу исправить ни один из них. Что, позвольте вам сказать, отнюдь не умно, а просто раздражает. - person Michael Kohne; 08.08.2010
comment
@Michael - да, справедливо. Возможно, на оригинальном указателе вы делаете не что-то глупое, а кто-то делает что-то глупое. - person Steve Jessop; 08.08.2010
comment
Годболт и Ардуино сказали мне, что правильность const не только для развлечения. - person dgrat; 14.09.2017
comment
@dgrat: У вас есть пример? - person Billy ONeal; 20.09.2017
comment
@BillyONeal Ну, на одну часть уже был дан ответ ниже, и ясно, какая версия должна быть немного быстрее. Для Arduino компилятор имеет тенденцию перемещать переменные с константой с большей вероятностью во флэш-память, а не в ОЗУ. Что и желательно, поскольку для микроконтроллеров меньшего размера объем оперативной памяти ограничен. - person dgrat; 21.09.2017
comment
@dgrat: Пометка данных как рожденных константой отличается от наблюдения за константной корректностью в базе кода. - person Billy ONeal; 21.09.2017
comment
Сравнивая приведенный выше ответ и этот ответ: stackoverflow.com/a/357607/3736444 - я тоже запутался. Я понял, что с const_cast вы не можете просто удалить const и работать с объектом, поскольку он не был const. Так что const мне кажется хорошим индикатором для оптимизаций ... Кто-нибудь может уточнить? - person Jarek C; 13.07.2020

Да, оно может.

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

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

https://godbolt.org/g/UEX4NB

C++:

int foo1 = 1;
const int foo2 = 2;

int get_foo1() {
    return foo1;
}

int get_foo2() {
    return foo2;
}

как м:

foo1:
        .long   1
foo2:
        .long   2
get_foo1():
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address
        pop     rbp
        ret
get_foo2():
        push    rbp
        mov     rbp, rsp
        mov     eax, 2 ; foo2 has been replaced with an immediate 2
        pop     rbp
        ret

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


Стив Джессоп приводит еще один пример в своем комментарии к исходному вопросу, который поднимает кое-что, о чем стоит упомянуть. В области видимости блока компилятор может определить, будет ли переменная изменена, и оптимизировать ее соответствующим образом, независимо от const, потому что компилятор может видеть все использования переменной. Напротив, в приведенном выше примере невозможно предсказать, будет ли foo1 изменен, поскольку он может быть изменен в других единицах перевода. Я полагаю, что гипотетический разумный ультракомпилятор может проанализировать всю программу и определить, допустим ли встроенный доступ к _11 _..., но настоящие компиляторы не могут.

person Praxeolitic    schedule 11.12.2016
comment
@ericcurtin Вот почему я не упомянул компилятор в ответе. Обычно при публикации сгенерированной сборки я обязательно указываю компилятор и версию, но это оптимизация, которую будет выполнять каждый основной оптимизирующий компилятор, поэтому я не хотел создавать впечатление, что это было характерно для одного компилятора. - person Praxeolitic; 13.03.2018
comment
@Acorn Вот тот же пример, но с объектом класса: godbolt.org/z/R-Zfgc. Кроме того, переменные в примере имеют внешнюю связь. - person Praxeolitic; 14.03.2019

Немного устарело, но все еще применяется: http://www.gotw.ca/gotw/081.htm И еще несколько: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

person Maxim Egorushkin    schedule 08.08.2010

по моему опыту нет

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

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

если вы ищете оптимизацию, вам следует подумать о _ 1_ или модификаторы / атрибуты специальных функций: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

person Anycorn    schedule 08.08.2010