const-correctness가 성능을 향상시킬 수 있습니까?


92

저는 C 또는 C ++ 코드에서 const-correctness를 적용하는 것이 유지 관리 측면에서 좋은 방법 일뿐만 아니라 컴파일러가 최적화를 수행 할 수 있도록 허용 할 수 있다는 것을 여러 번 읽었습니다. 그러나 나는 그 반대도 읽었다. 이것은 성능에 전혀 영향을주지 않는다는 것이다.

따라서 const 정확성이 프로그램의 성능을 향상시키는 데 컴파일러에 도움이 될 수있는 예가 있습니까?


50
Const-correctness는 유지 관리와 관련하여 가장 좋은 방법 중 하나입니다. C ++ 코드가 const에 맞지 않으면 기본적으로 재앙이 닥칠 때까지 기다리는 쓰레기 더미입니다. 성능에 영향을주지 않습니다.

2
@Neil Butterworth : 불행히도 그 반대는 사실이 아닙니다.
Beta

6
다음 const은 성능 차이를 만든 예입니다 . stackoverflow.com/questions/1121791/… . 하지만 본질적으로 구현 품질 문제였습니다. const컴파일러 합법적으로 최적화를 수행 할 수 있는지 여부를 결정하지 않았으며 컴파일러 버전이 누락되었을 때이를 수행하지 못하는 경우가 발생했습니다.
Steve Jessop

3
나는 "morgennebel"이 첫 문장에서 'only'를 놓쳤다 고 확신합니다. "is not only a good practice"라는 말이 훨씬 더 합리적입니다.
IanH

2
@IanH 네, 고려했습니다. 그러나 OP는 명확히 할 충분한 시간이 있습니다. 나는 질문을 게시하고 단순히 사라지는 사람들에 의해 정말 흥분됩니다.

답변:


77

const때문에 정확성은 성능을 개선 할 수 const_castmutable언어, 그리고 일치되게 규칙을 깰 코드를 할 수 있습니다. 이것은 C ++ 11에서 더욱 악화됩니다. const예를 들어 데이터가에 대한 포인터 일 수 있습니다 std::atomic. 즉, 컴파일러는 다른 스레드에 의해 변경된 내용을 존중해야합니다.

즉, 컴파일러가 생성하는 코드를보고 주어진 변수에 실제로 쓰는지 확인하고 그에 따라 최적화를 적용하는 것은 간단합니다.

즉, const정확성은 유지 관리 측면에서 좋은 것입니다. 그렇지 않으면 클래스의 클라이언트가 해당 클래스의 내부 멤버를 손상시킬 수 있습니다. 예를 들어 표준을 고려하십시오 std::string::c_str(). const 값을 반환 할 수 없다면 문자열의 내부 버퍼를 사용할 수 있습니다!

const성능상의 이유로 사용하지 마십시오 . 유지 관리를 위해 사용하십시오.


31
"현의 내부 버퍼로 나사를 조일 수있을 것입니다!" -결정적으로, 내부 버퍼 로 실수로 나사를 조일 수 있습니다 . 로 인한 컴파일러 오류 const는 "당신은 어리석은 일을하고 있습니다"라는 표지판입니다.
Steve Jessop

4
... 그리고 const-cast는 "이 코드의 작성자는 뭔가 영리한 일을하려고합니다"라고 말하는 표지판입니다. ;-)
Steve Jessop

5
@Steve Jessop-또는 const-cast는 "const-correct 코드 묶음을 상수가 아닌 코드로 묶으려고하는데 둘 중 하나를 고칠 수 없습니다"라는 표지판입니다. 제가 말씀 드리죠. 영리하지 않고 성가신 일입니다.
Michael Kohne

7
@Michael-예, 공정한 지적입니다. 아마도 원래 이정표는 "당신은 어리석은 일을하고 있습니다"가 아니라 "누군가 어리석은 일을하고 있습니다"가 아닐 것입니다.
Steve Jessop

Godbolt와 Arduino는 const 정확성이 재미만을위한 것이 아니라고 말했습니다.
dgrat

31

예, 그럴 수 있습니다.

대부분 const의 s는 순전히 프로그래머의 이익을위한 것이며 컴파일러가 최적화하는 데 도움이되지 않습니다. 그러나 일부 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;
}

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하지만 실제 컴파일러는 그렇게 할 수 없습니다.


@ericcurtin 그래서 대답에서 컴파일러를 언급하지 않았습니다. 일반적으로 생성 된 어셈블리를 게시 할 때 컴파일러와 버전을 명시해야하지만 이것은 모든 주요 최적화 컴파일러가 수행 할 최적화이므로 이것이 하나의 컴파일러에만 해당된다는 인상을주고 싶지 않았습니다.
Praxeolitic

1
@Acorn 다음은 동일한 예제이지만 클래스 객체가있는 경우 : godbolt.org/z/R-Zfgc . 또한 예제의 변수에는 외부 연결이 있습니다.
Praxeolitic

6

내 경험상, 아니

스칼라 변수의 경우 컴파일러는 값이 변경 될 때마다 결정하고 필요한 최적화를 자체적으로 수행 할 수 있습니다.

배열 포인터의 경우 const 정확성은 잠재적 인 앨리어싱 문제가있을 때 값이 실제로 일정하다는 것을 보장하지 않습니다. 따라서 컴파일러는 최적화를 수행하기 위해 const 한정자를 단독으로 사용할 수 없습니다.

최적화를 찾고 있다면, __restrict__또는 특수 함수 수정 자 / 속성을 고려해야 합니다 : http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.