2010-08-08 5 views
58

Я читал много раз, что принудительное выполнение const-корректности в коде C или C++ является не только хорошей практикой в ​​отношении ремонтопригодности, но также может позволить вашему компилятору выполнять оптимизации. Тем не менее, я прочитал полную противоположность, тоже —, что она вообще не влияет на производительность.Может ли const-correctness повысить производительность?

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

+42

Const-correctness - одна из лучших практик в отношении ремонтопригодности. Если ваш код на C++ не является константным, это в основном куча дерьма, ожидающая катастрофы. Он не предназначен для воздействия на производительность. – 2010-08-08 16:23:00

+1

@Neil Butterworth: к сожалению, инверсия неверна. – Beta

+3

Вот пример, где 'const' сделал разницу в производительности: http://stackoverflow.com/questions/1121791/optimisation-of-division-in-gcc. Тем не менее, это была проблема качества исполнения. 'const' не определил, может ли компилятор * законно сделать оптимизацию, просто случилось, что версия компилятора не удалось выполнить, когда она отсутствовала. –

ответ

50

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

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

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

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

+26

«вы сможете закрутить внутренний буфер строки!» - Реально, вы можете * случайно * прикрутить внутренний буфер. Ошибки компилятора из-за 'const' являются указателями, говорящими:« Вы делаете что-то глупое ». –

+1

@Steve: Хорошая точка. +1 для комментариев. –

+4

... и const-casts являются указателями, говорящими: «автор этого кода пытается сделать что-то умное» ;-) –

6

в моем опыте, не

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

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

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

13

Да, это возможно.

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

В качестве примера, доступ к глобальной переменной, определенной с помощью типа 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; 
} 

ASM:

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 не является оптимизацией.


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

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