소년코딩

04.02 - 지역 변수, 스코프 그리고 주기 (Local variables, scope and duration)

변수를 논의할 때 변수의 스코프(=범위)와 주기의 개념을 분리하는 것이 유용하다. 

변수의 스코프(scope)에 따라 변수에 접근할 수 있는 위치가 결정된다. 

변수의 주기(duration)는 변수가 생성되고 소멸하는 위치를 결정한다. 

이 두 개념은 밀접하게 관련돼있다.

함수 내부에 정의된 변수를 지역 변수(local variable)라고 한다. 지역 변수는 자동 주기(auto duration)를 가지고 있다. 정의되는 시점에서 생성되고 초기화되며, 정의된 블록이 끝나는 지점에서 소멸한다. 또한, 지역 변수는 지역 스코프(블록 스코프라고도 불린다)를 가진다. 이는 선언 시점에서 스코프에 들어가고 정의된 블록 끝에서 소크프에서 벗어나는 걸 의미한다. 스코프 내에서만 변수에 접근할 수 있다.

int main()
{
    int i(5);      // i created and initialized here
    double d(4.0); // d created and initialized here

    return 0;

} // i and d go out of scope and are destroyed here

변수 idmain() 함수 내부에서 정의되었기 때문에 main() 함수의 실행이 완료되면 모두 소멸한다.

중첩된 블록(nested block) 내부에 정의된 변수는 중첩된 블록이 끝나는 즉시 소멸한다.

int main() // outer block
{
    int n(5); // n created and initialized here

    { // begin nested block
        double d(4.0); // d created and initialized here
    } // d goes out of scope and is destroyed here

    // d can not be used here because it was already destroyed!

    return 0;
} // n goes out of scope and is destroyed here

블록 내부에 정의된 변수는 해당 블록에서만 접근할 수 있다. 각 함수는 자체 블록을 가지고 있으므로 한 함수의 변수를 다른 함수에서 볼 수 없다.

void someFunction()
{
    int value(4); // value defined here

    // value can be seen and used here

} // value goes out of scope and is destroyed here

int main()
{
    // value can not be seen or used inside this function.

    someFunction();

    // value still can not be seen or used inside this function.

    return 0;
}

다음 예제를 보면 두 함수 각각에 x, y 이름의 변수가 있다. 각 함수의 이러한 변수는 다른 함수에 같은 이름을 가진 다른 변수의 존재를 알지 못한다.

#include <iostream>

// add's x and y can only be seen/used within function add() 
int add(int x, int y) // add's x and y are created here and can only be seen/used within add() after this point
{
    return x + y;
} // add's x and y are destroyed here

// main's x and y can only be seen/used within function main() 
int main()
{
    int x = 5; // main's x is created here, and can be seen/used only within main() after this point
    int y = 6; // main's y is created here, and can be seen/used only within main() after this point

    std::cout << add(x, y) << std::endl; // the value from main's x and y are copied into add's x and y

    // We can still use main's x and y here

    return 0;
} // main's x and y are destroyed here

중첩된 블록은 외부 블록의 일부로 간주한다. 따라서 외부 블록에서 정의된 변수를 중첩된 블록 내부에서 접근할 수 있다.

#include <iostream>

int main()
{ // start outer block

    int x(5);

    { // start nested block
        int y(7);
        // we can see both x and y from here
        std::cout << x << " + " << y << " = " << x + y;
    } // y destroyed here

    // y can not be used here because it was already destroyed!

    return 0;
} // x is destroyed here

쉐도잉 (shadowing)

중첩된 블록 내부의 변수는 외부 블록과 같은 이름을 가질 수 있다. 이 경우 외부 블록의 같은 이름의 변수는 잠시 가려지는데 이것을 쉐도잉(shadowing) 또는 숨기기(hide)라고 부른다.

#include <iostream>

int main()
{ // outer block
    int apples(5); // here's the outer block apples

    if (apples >= 5) // refers to outer block apples
    { // nested block
        int apples; // hides previous variable named apples

        // apples now refers to the nested block apples
        // the outer block apples is temporarily hidden

        apples = 10; // this assigns value 10 to nested block apples, not outer block apples

        std::cout << apples << '\n'; // print value of nested block apples
    } // nested block apples destroyed

    // apples now refers to the outer block apples again

    std::cout << apples << '\n'; // prints value of outer block apples

    return 0;
} // outer block apples destroyed

If you run this program, it prints:

10
5

위 프로그램에서 중첩된 블록 내부의 변수 apple은 외부 블록 apple을 숨긴다. 중첩된 블록이 끝나면 중첩된 블록 내부 변수 apple 은 소멸하고 다시 외부 블록 apple에 접근할 수 있게 된다.

만약 중첩된 블록 내부에서 변수 apple을 정의하지 않으면 외부 블록 변수 apple에 접근하여 값 10을 할당한다.

#include <iostream>

int main()
{ // outer block
    int apples(5); // here's the outer block apples

    if (apples >= 5) // refers to outer block apples
    { // nested block
        // no inner block apples defined

        apples = 10; // this now applies to outer block apples, even though we're in an inner block

        std::cout << apples << '\n'; // print value of outer block apples
    } // outer block apples retains its value even after we leave the nested block

    std::cout << apples << '\n'; // prints value of outer block apples

    return 0;
} // outer block apples destroyed

If you run this program, it prints:

10
10

중첩된 블록 안에서 외부 블록의 변수와 이름이 같은 변수를 정의하지 말자. 변수는 가능한 한 제한된 스코프(=범위) 안에서 정의되는게 좋다. 예를 들어, 변수가 중첩된 블록 내에서만 사용되는 경우, 해당 중첩된 블록 내에서 정의되도록 하자.


함수 매개 변수 (function parameter)

함수 매개 변수는 함수가 속하는 블록 내에서 정의되지는 않았지만 대부분 블록 스코프를 가진 것으로 간주할 수 있다.

int max(int x, int y) // 변수 x와 y는 함수 매개 변수에서 정의되었다.
{
    // 매개변수는 블록 스코프를 가진것으로 간주되므로 블록 내부에서 접근가능하다.
    // x와 y중 더 큰 값을 변수 max에 할당한다.
    int max = (x > y) ? x : y;
    return max;
} // 변수 x와 y는 여기서 소멸된다.

요약 (Summary)

함수 내부에서 정의된 변수를 지역 변수(= 로컬 변수)라고 한다. 이러한 지역 변수는 해당 변수가 정의된 블록(+중첩된 블록) 내에서만 접근할 수 있으며, 블록이 끝나는 즉시 소멸한다.

변수를 사용할 최소 범위(=스코프)에서 정의하는 게 좋다. 변수가 중첩된 블록 내에서만 사용되는 경우 중첩된 블록 내에서 변수를 정의한다.


cpp 번역: 이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/4-1a-local-variables-and-local-scope/ 입니다.

댓글 로드 중…

블로그 정보

소년코딩 - 소년코딩

소년코딩, 자바스크립트, C++, 물리, 게임 코딩 이야기

최근에 게시된 이야기