이것은 훌륭한 연습입니다.
루프 내부에 변수를 작성하면 해당 범위가 루프 내부로 제한됩니다. 루프 외부에서 참조하거나 호출 할 수 없습니다.
이 방법:
변수의 이름이 "generic"과 같은 비트 (예 : "i")이면 나중에 코드에서 같은 이름의 다른 변수와 혼합 할 위험이 없습니다 ( -Wshadow
GCC 의 경고 명령어를 사용하여 완화 할 수도 있음 ).
컴파일러는 변수 범위가 루프 내부로 제한되므로 변수가 실수로 다른 곳에서 참조되는 경우 적절한 오류 메시지를 발행합니다.
마지막으로, 일부 전용 최적화는 변수가 루프 외부에서 사용될 수 없다는 것을 알고 있기 때문에 컴파일러 (가장 중요한 레지스터 할당)에 의해보다 효율적으로 수행 될 수 있습니다. 예를 들어, 나중에 재사용하기 위해 결과를 저장할 필요가 없습니다.
요컨대, 당신은 그것을 할 권리가 있습니다.
그러나 변수는 각 루프 사이에 값을 유지하지 않아야합니다 . 이 경우 매번 초기화해야 할 수도 있습니다. 루프를 포괄하는 더 큰 블록을 만들 수도 있는데, 그 목적은 한 루프에서 다른 루프로 값을 유지해야하는 변수를 선언하는 것입니다. 여기에는 일반적으로 루프 카운터 자체가 포함됩니다.
{
int i, retainValue;
for (i=0; i<N; i++)
{
int tmpValue;
/* tmpValue is uninitialized */
/* retainValue still has its previous value from previous loop */
/* Do some stuff here */
}
/* Here, retainValue is still valid; tmpValue no longer */
}
질문 # 2의 경우 : 함수가 호출 될 때 변수가 한 번 할당됩니다. 실제로 할당 관점에서 보면 함수 시작 부분에서 변수를 선언하는 것과 거의 같습니다. 유일한 차이점은 범위입니다. 변수는 루프 외부에서 사용할 수 없습니다. 변수가 할당되지 않았을 수도 있습니다. 사용 가능한 슬롯 (범위가 종료 된 다른 변수에서)을 다시 사용하기 만하면됩니다.
제한적이고 정확한 범위로보다 정확한 최적화가 이루어집니다. 그러나 더 중요한 것은 코드의 다른 부분을 읽을 때 걱정할 필요가 적은 상태 (예 : 변수)로 코드를 더 안전하게 만듭니다.
이것은 if(){...}
블록 외부에서도 마찬가지 입니다. 일반적으로 대신 :
int result;
(...)
result = f1();
if (result) then { (...) }
(...)
result = f2();
if (result) then { (...) }
작성하는 것이 더 안전합니다.
(...)
{
int const result = f1();
if (result) then { (...) }
}
(...)
{
int const result = f2();
if (result) then { (...) }
}
특히 작은 예에서는 차이가 작게 보일 수 있습니다. 그러나 더 큰 코드 기반에서는 도움이 될 것입니다. 이제 일부 result
값 f1()
을 f2()
블록 으로 전송할 위험이 없습니다 . 각각 result
은 자체 범위로 엄격히 제한되어 역할이 더욱 정확합니다. 리뷰어의 관점에서 보면 걱정하고 추적해야 할 장거리 상태 변수 가 적기 때문에 훨씬 좋습니다.
컴파일러가 더 나은 도움을 줄 것입니다. 미래에 약간의 잘못된 코드 변경 후으로 result
제대로 초기화되지 않았다고 가정합니다 f2()
. 두 번째 버전은 컴파일 타임에 명확한 오류 메시지 (런타임보다 낫다)를 나타내는 작동을 거부합니다. 첫 번째 버전은 아무 것도 발견하지 못합니다. 그 결과 f1()
는 단순히 두 번째로 테스트되어 결과에 대해 혼란스러워 f2()
집니다.
보완 정보
오픈 소스 도구 인 CppCheck (C / C ++ 코드를위한 정적 분석 도구)는 최적의 변수 범위에 관한 훌륭한 힌트를 제공합니다.
할당에 대한 의견에 대한 답변 : 위의 규칙은 C에서는 true이지만 일부 C ++ 클래스에는 해당되지 않을 수 있습니다.
표준 유형 및 구조의 경우 변수 크기는 컴파일 타임에 알려져 있습니다. C에는 "구성"과 같은 것이 없으므로 함수를 호출 할 때 변수를위한 공간이 스택에 할당됩니다 (초기화없이). 이것이 루프 내부에서 변수를 선언 할 때 "제로"비용이 발생하는 이유입니다.
그러나 C ++ 클래스의 경우이 생성자 항목이 훨씬 적습니다. 컴파일러는 동일한 공간을 재사용하기에 충분히 영리해야하기 때문에 할당이 문제가되지 않을 것이라고 생각하지만 초기화는 각 루프 반복에서 발생할 수 있습니다.