const 사용 (Use of const)¶
API에서는 의미가 있을 때마다 const를 사용하세요. constexpr은 const의 일부 용도에 더 나은 선택입니다.
선언된 변수와 매개변수는 변수가 변경되지 않았음을 나타내기 위해 const 키워드 앞에 올 수 있습니다(예: const int foo ). 클래스 함수는 함수가 클래스 멤버 변수의 상태를 변경하지 않음을 나타내기 위해 const 한정자를 가질 수 있습니다(예: class Foo { int Bar(char c) const; }; ).
변수가 어떻게 사용되는지 사람들이 더 쉽게 이해할 수 있습니다. 컴파일러가 더 나은 유형 검사를 수행하고 아마도 더 나은 코드를 생성할 수 있습니다. 호출하는 함수가 변수를 수정하는 방법에 따라 제한된다는 것을 알기 때문에 사람들이 프로그램의 정확성을 스스로 확신하는 데 도움이 됩니다. 다중 스레드 프로그램에서 잠금 없이 사용하기에 안전한 기능이 무엇인지 사람들이 알 수 있도록 도와줍니다.
const는 바이러스성입니다. const 변수를 함수에 전달하는 경우 해당 함수의 프로토타입에는 const가 있어야 합니다(그렇지 않으면 변수에 const_cast가 필요함). 이는 라이브러리 함수를 호출할 때 특히 문제가 될 수 있습니다.
의미 있고 정확하다면 API(예: 함수 매개변수, 메서드 및 비지역 변수)에서 const를 사용하는 것이 좋습니다. 이는 작업이 변경할 수 있는 개체에 대한 일관되고 대부분 컴파일러에서 검증된 문서를 제공합니다. 읽기와 쓰기를 구별하는 일관되고 안정적인 방법을 갖는 것은 스레드로부터 안전한 코드를 작성하는 데 중요하며 다른 많은 상황에서도 유용합니다. 특히:
- 함수가 참조 또는 포인터로 전달된 인수를 수정하지 않을 것이라고 보장하는 경우 해당 함수 매개변수는 각각 상수에 대한 참조( const T& ) 또는 상수에 대한 포인터( const T* )여야 합니다.
- 값으로 전달된 함수 매개변수의 경우 const는 호출자에게 영향을 주지 않으므로 함수 선언에서는 권장되지 않습니다. TotW #109를 참조하세요.
- 객체의 논리적 상태를 변경하지 않는 한(또는 사용자가 const가 아닌 참조를 반환하여 해당 상태를 수정할 수 있도록 허용하지만 그런 경우는 드물지만) 메서드를 const로 선언하거나 동시에 안전하게 호출할 수 없습니다.
지역 변수에 const를 사용하는 것은 권장되지도 권장되지도 않습니다.
클래스의 모든 const 작업은 서로 동시에 호출해도 안전해야 합니다. 이것이 가능하지 않은 경우 클래스는 "스레드가 안전하지 않음"으로 명확하게 문서화되어야 합니다.
어떤 사람들은 int const foo 형식보다 const int foo 형식을 선호합니다. 그들은 이것이 더 일관적이기 때문에 더 읽기 쉽다고 주장합니다. 즉, const가 항상 설명하는 객체를 따른다는 규칙을 유지합니다. 그러나 대부분의 const 표현식에는 const 하나만 있고 기본 값에 적용되므로 깊이 중첩된 포인터 표현식이 거의 없는 코드베이스에는 이 일관성 인수가 적용되지 않습니다. 이러한 경우에는 일관성을 유지할 수 없습니다. const를 먼저 넣는 것이 더 읽기 쉽습니다. "명사"( int ) 앞에 "형용사"( const )를 넣는 영어를 따르기 때문입니다.
즉, const를 먼저 배치하는 것을 권장하지만 필수는 아닙니다. 하지만 주변의 코드와 일관성을 유지하세요!
이해하기 쉽게 설명하기¶
핵심: 의미가 있으면 API에 const를 붙여라¶
함수 매개변수, 메서드, 비지역 변수 등 API에서 의미가 맞으면 const를 쓰세요. 무엇이 바뀌고 무엇이 안 바뀌는지를 컴파일러가 검증하는 문서로 남기는 셈이며, 스레드 안전성 추론에도 중요합니다.
어디에 붙이나¶
- 참조·포인터로 받은 인자를 수정하지 않으면 →
const T&,const T* - 값으로 받는 매개변수의
const는 호출자에게 영향이 없으므로 선언부에 쓰지 않는 게 권장됩니다. - 객체의 논리적 상태를 바꾸지 않는 메서드 →
const메서드. 클래스의 모든const연산은 서로 동시 호출에 안전해야 합니다(아니면 "스레드 안전하지 않음"을 명확히 문서화). - 지역 변수의
const는 권장도 비권장도 아닙니다(자유).
참고¶
- 진짜 상수라면
constexpr이 더 맞는 경우가 많습니다. const는 전염성이 있습니다 —const값을 넘기면 받는 함수의 시그니처도const여야 합니다(아니면const_cast가 필요).- 위치는
const int* p(const 먼저)를 권장하지만 필수는 아닙니다. 주변 코드와 일관되게 하세요.