변수를 함수 맨 위에 선언하시겠습니까, 아니면 별도의 범위로 선언하시겠습니까?
방법 1과 방법 2 중 어느 것이 더 좋습니까?
방법 1:
LRESULT CALLBACK wpMainWindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hwnd, &rc);
hdc = BeginPaint(hwnd, &ps);
// drawing here
EndPaint(hwnd, &ps);
break;
}
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
return 0;
}
방법 2:.
LRESULT CALLBACK wpMainWindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
switch (msg)
{
case WM_PAINT:
GetClientRect(hwnd, &rc);
hdc = BeginPaint(hwnd, &ps);
// drawing here
EndPaint(hwnd, &ps);
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
return 0;
}
방법 1에서 wpMainWindow 함수가 호출되었을 때 msg = WM_PAINT일 경우 처음에 스택 상의 모든 변수에 메모리를 할당합니까?또는 WM_PAINT 범위에 들어갈 때만?
방법 1은 메시지가 WM_PAINT일 때만 메모리를 사용하고 방법 2는 어떤 메시지와 동일한 메모리를 사용합니까?
변수는 가능한 한 로컬로 선언해야 합니다.
변수를 "함수의 맨 위에" 선언하는 것은 항상 끔찍할 정도로 나쁜 관행입니다.변수를 선언할 수 있는 C89/90 언어에서도 변수를 가능한 한 로컬로 선언하는 것이 좋습니다.즉, 변수의 원하는 수명을 커버하는 최소 로컬블록의 선두에서 선언하는 것이 좋습니다.변수 선언의 '로컬화'만을 목적으로 한 '용장' 로컬블록을 도입하는 것이 타당할 수 있습니다.
C++ 와 C99 에서는, 코드의 어느 장소에서도 변수를 선언할 수 있습니다.즉, 각 변수를 가능한 한 로컬로 선언하고, 처음 사용하는 지점에 최대한 가깝게 선언합니다.그 주된 근거는 대부분의 경우 선언 시점에서 변수에 의미 있는 이니셜라이저를 제공할 수 있다는 것입니다(인테셜라이저를 사용하지 않거나 더미 이니셜라이저를 사용하지 않고 선언하는 대신).
메모리 사용량에 대해서는 일반적으로 일반적인 구현에서는 동시에 존재하는 모든 변수에 필요한 최대 공간이 즉시 할당됩니다(함수 입력 시).그러나 선언 습관은 해당 공간의 정확한 크기에 영향을 미칠 수 있습니다.예를 들어 이 코드에서는
void foo() {
int a, b, c;
if (...) {
}
if (...) {
}
}
세 변수 모두 동시에 존재하며 일반적으로 세 변수 모두에 대한 공간을 할당해야 합니다.하지만 이 코드에서는
void foo() {
int a;
if (...) {
int b;
}
if (...) {
int c;
}
}
즉, 즉, 2개의 )에 됩니다(즉, 2개의 변수 전용 공간(즉, 2개의 변수만 할당됩니다.b
★★★★★★★★★★★★★★★★★」c
을 참조)이는 변수를 가능한 한 로컬로 선언해야 하는 또 다른 이유입니다.
케이스 1이 구현 정의되어 있는 경우 스택에 할당되어 있는지 여부.구현에는 스택이 필요하지 않습니다.
로컬 변수 영역 전체에 대해 스택포인터로부터 1개의 값을 감산하는(아래쪽으로 늘어나는 스택의 경우) 조작이 되기 때문에 보통 이 작업은 그다지 느리지 않습니다.
여기서 중요한 것은 스코프가 가능한 한 로컬이어야 한다는 것입니다.즉, 변수를 가능한 한 늦게 선언하고 필요한 만큼만 주변에 유지하십시오.
여기서 선언하는 것은 공간을 할당하는 것과는 다른 추상화 수준입니다.실제 공간은 함수의 시작 부분(실장 수준)에 할당할 수 있지만, 이러한 변수는 범위가 지정되는 동안(C 수준)에만 사용할 수 있습니다.
정보의 인접성은 정보의 사촌과 마찬가지로 캡슐화가 중요합니다.
나는 방법 3을 좋아합니다.
LRESULT wpMainWindowPaint(HWND hwnd)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hwnd, &rc);
hdc = BeginPaint(hwnd, &ps);
// drawing here
EndPaint(hwnd, &ps);
return 0;
}
LRESULT CALLBACK wpMainWindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_PAINT: return wpMainWindowPaint(hwnd);
default: return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
조직 목적을 위해 자신의 영역을 가질 자격이 있다면, 그것은 그 자체의 기능을 가질 자격이 있다.함수 호출 오버헤드가 우려되는 경우 인라인으로 합니다.
코드를 최적화하는 것은 컴파일러의 일이며, 1시간의 컴파일러 시간은 1시간보다 훨씬 저렴하고, 변수가 선언된 위치를 확인하기 위해 코드를 위아래로 스크롤해야 할 경우 시간이 낭비되기 때문에 회사에서는 가능한 한 모든 것을 로컬로 유지하고 싶다고 생각합니다.
'가장 작은 블록'이 아니라 '사용하는 곳만큼'을 말하는 거야!
LRESULT CALLBACK wpMainWindow(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_PAINT:
{
RECT rc;
GetClientRect(hwnd, &rc);
{ // sometimes I even create an arbitrary block
// to show correlated statements.
// as a side-effect, the compiler may not need to allocate space for
// variables declared here...
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// drawing here
EndPaint(hwnd, &ps);
}
break;
}
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
return 0;
}
Java 프로그래밍 언어에서는 일반적으로 메서드에서 필요한 경우에만 로컬 변수를 선언합니다.
void foo(int i) {
if (i == 1)
return;
Map map1 = new HashMap();
if (i == 2)
return;
Map map2 = new HashMap();
}
C++ 프로그래밍 언어의 경우, 간단한 생성자가 아닌 변수를 선언하는 것은 실행 비용을 수반하기 때문에 동일한 방법을 제안합니다.이러한 모든 선언을 메서드의 선두에 배치하면 이들 변수 중 일부가 사용될 경우 불필요한 비용이 발생합니다.
void foo(int i)
{
if (i == 1)
return;
std::map<int, int> map1; // constructor is executed here
if (i == 2)
return;
std::map<int, int> map2; // constructor is executed here
}
C에게는 이야기가 다르다.아키텍처와 컴파일러에 따라 달라집니다.x86 및 GCC의 경우 모든 선언을 함수 시작 위치에 두고 필요한 경우에만 변수를 선언하는 것이 동일한 성능을 가집니다.그 이유는 C 변수에는 생성자가 없기 때문입니다.이러한 2가지 접근법에 의한 스택메모리 할당에 대한 영향은 동일합니다.다음은 예를 제시하겠습니다.
void foo(int i)
{
int m[50];
int n[50];
switch (i) {
case 0:
break;
case 1:
break;
default:
break;
}
}
void bar(int i)
{
int m[50];
switch (i) {
case 0:
break;
case 1:
break;
default:
break;
}
int n[50];
}
두 기능 모두 스택 조작용 어셈블리 코드는 다음과 같습니다.
pushl %ebp
movl %esp, %ebp
subl $400, %esp
Linux 커널 코드에서는 모든 선언을 함수로 시작하는 것이 일반적입니다.
관련된 가장 좁은 범위에서 변수를 정의합니다.제 의견으로는 위의 방법 2를 사용할 이유가 없습니다.
스택 공간은 변수가 범위 내에 있을 때만 사용됩니다.@paxdiablo가 지적한 것처럼 컴파일러가 공간을 찾을 수 있다면 로컬은 스택이 아닌 레지스터에 저장될 수 있습니다.
메모리 할당은 표준에서 이 세부 사항에 대해 명시되어 있지 않으므로 실제 답변을 위해서는 컴파일러와 플랫폼을 지정해야 합니다.성능에는 문제가 되지 않습니다.
필요한 것은 가독성입니다.일반적으로 이 작업은 최소한의 사용 가능한 범위에서 변수를 선언함으로써 이루어집니다.적절한 값으로 즉시 초기화할 수 있는 것이 좋습니다.변수의 범위가 작을수록 예측 불가능한 방식으로 잠재적으로 프로그램의 나머지 부분과 상호 작용할 수 있습니다.초기화에 가까운 선언일수록 나쁜 일이 일어날 기회가 줄어듭니다.
아마 더 좋을 것 같은 건
RECT rc;
GetClientRect(hwnd, &rc);
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
이건 C++용이에요.C의 경우 이전 버전의 C는 모든 변수를 블록의 맨 위에 선언해야 한다는 점을 제외하고는 규칙은 비슷합니다.
어느 시점에서 스택 예약이 완료되었는지 알 수 없습니다.
가독성을 위해 C99(또는 C++)로 하겠습니다.이를 통해 변수를 처음 사용하는 곳에서 변수를 선언할 수 있습니다.
HDC hdc = BeginPaint(hwnd, &ps);
사용되지 않을 수 있는 변수로 스택을 오염시킬 필요가 없습니다.사용 직전에 변수를 할당합니다.을 간과하다RECT rc
에의 후속 콜.GetClientRect
벤 보이트의 방법이 최선이다.
언급URL : https://stackoverflow.com/questions/3773396/declare-variables-at-top-of-function-or-in-separate-scopes
'programing' 카테고리의 다른 글
Java에서 환경변수를 설정하려면 어떻게 해야 합니까? (0) | 2022.07.13 |
---|---|
휴지 모드와 스프링 데이터 JPA의 차이점은 무엇입니까? (0) | 2022.07.13 |
Java에서 현재 날짜/시간을 가져오는 방법 (0) | 2022.07.13 |
nuxt 프로젝트에 store/index.js 파일이 없습니다. (0) | 2022.07.13 |
일상적인 기계는 어떻게 프로그램됩니까? (0) | 2022.07.13 |