본문 바로가기
C++

[C++ Core Guidelines] I.2 전역 변수는 상수로 만들자

by 코드쉼터 2024. 4. 30.

I.2: Avoid non-const global variables

 

이유

일반 전역 변수의 사용은 숨겨진 의존성을 만들고 실행 흐름을 예측하기 여럽게 합니다.

 

 

예시 (나쁜 예)

struct Data {
    // ... 엄청 긴 코드 ...
} data;            // non-const data

void compute()     // 나쁨
{
    // ... data 사용함 ...
}

void output()     // 나쁨
{
    // ... data 사용함 ...
}

위처럼 엄청 긴 코드에서 일반 전역 변수 data 가 여러 함수에 걸쳐 사용되고 있다고 한다면, 누가 최종적으로 data 를 사용했는지 알기가 쉽지 않습니다.

함수만 따로 분리해서 테스트하는 유닛 테스팅을 어렵게 만들고, compute() 함수를 병렬 처리하려면 data 변수를 매번 lock 하고 unlock 해야 할 것입니다.

 

 

정리

1.

컴파일러는 꼭 constexpr 로 작성하지 않더라도 memoization, interprocedural constant propagation 과 같은 기법을 통해 상수화된 코드를 보다 잘 최적화합니다. (명령어 사이에 불필요한 의존성을 줄입니다)

2.

전역 개체의 초기화는 순서대로 이루어진다는 보장이 없기 때문에 리터럴 상수로 초기화 하는 것이 안전합니다. 물론 const 개체의 경우에도 초기화 순서를 보장하진 않습니다.

3.

사실 전역 개체의 사용은 싱글톤 패턴보다 나은 경우가 많습니다. (싱글톤도 어차피 전역 변수처럼 외부에 노출되기 때문)

그런 면에서 전역 상수는 옳습니다.

4.

병렬 처리에서 변경 가능한 데이터, 참조, 포인터는 전부 잠재적인 경쟁 대상입니다.

5.

잦은 복사를 피하기 위해 전역 변수를 사용하는 경우, 차라리 const 참조로 전달하세요.
아니면 데이터를 일부 개체의 상태로 정의하고 작업을 멤버 함수로 정의하세요. (클래스화)

6.

전역 변수를 만들지 말랬다고 전역으로 상수 포인터나 참조를 만들어서 일반 변수에 접근하는 요행을 부리지 마세요.

어차피 그런 방법으로는 숨겨진 종속성이나 잠재적인 경쟁 조건 문제를 해결하지 못합니다.

 

 

참고자료

https://mystyle1057.tistory.com/entry/C%EC%96%B8%EC%96%B4-%EA%B0%95%EC%A2%8C-%EC%98%A4%EB%A5%98%EC%B2%98%EB%A6%AC-errno-strerror-strerrorr