티스토리 뷰

저번 시간에는 함수의 기본을 알아보고 프로그램을 조금 더 쉽지만 복잡하게 코딩하는 방법을 알아보았습니다. 


함수는 어떤 건지, 반환 값, 함수 오버로딩, 함수 원형까지 꽤나 다양하게 배웠습니다.


이번 시간에는 함수를 조금 더 깊게 알아보겠습니다. 


기본인수


C++ 은 기본인수 값으로 함수를 선언할 수 있습니다. 인수가 없는 상태로 함수를 호출하면 기본 값이 할당되어 매개변수로 전달됩니다.


이 말은 함수를 선언해줄 때, 함수의 인수값을 미리 할당해 줌으로 기본 값을 프로그래머 임의로 지정해줄수 있다는 말이됩니다.


예제로 확인해봅시다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
 
void printArea(double radious = 1)
{
    double area = radious * radious * 3.14159;
    cout << "area is " << area << endl;
}
 
int main()
{
    printArea();
    printArea(4);
 
    return 0;
}
cs


4행에서 printArea 함수를 선언해주고 있습니다. 


그런데 헤더 부분을 보면 이전 시간에서는 함수가 받을 매개변수를 만들어줄때 값을 할당한적은 없었습니다. 확인하고 오셔도 좋습니다.


근데 이번 시간 예제에서는 변수를 선언해줌과 동시에 초기화도 해주고 있습니다. 이것이 기본인수를 할당해주는 방법입니다.


기본인수가 할당이 되면 이점이 있습니다.


12행을 보면 매개변수를 받지 않은 함수를 호출하고 있습니다. 


그런데 이 함수는 선언할 때부터 매개변수가 있는 함수입니다. 


매개변수가 없는 함수들이 있다고 지난시간에 소개했지만. 매개변수가 없는 것과 매개변수가 존재함에도 매개변수를 적지 않는 것은 약간의 차이가 있습니다.


그러므로 원래는 이 함수 호출은 오류를 부릅니다.


그러나 우리가 4행에서 기본인수를 선언해준 덕분에 이 함수호출은 오류를 내지않고 정상적으로 출력이 됩니다.


이것이 우리가 기본인수를 사용하는 이유입니다.


기본인수를 선언할 때 규칙이 있습니다. 


첫번째, 기본인수와 보통인수가 같이 선언될 때는 기본인수는 매개변수 목록의 맨 마지막에 선언되어야 합니다.

1
2
3
4
5
void t1(int x, int y = 0int z); // 잘못된 경우
void t2(int x = 0int y = 0int z); // 잘못된 경우
 
void t3(int x, int y = 0int z = 0); // 올바른 경우
void t4(int x= 0int y = 0int z = 0); // 올바른 경우
cs


두번째, 인수를 함수에서 삭제할 때 그 인수 뒤에 있는 모든 인수들도 함께 삭제해야 됩니다.

1
2
3
4
5
t3(1, , 20);
t4(, , 20); // 잘못된 경우
 
t3(1); // y, z 매개변수는 기본 값 할당
t4(12); // z 매개변수는 기본 값 할당
cs


이런식입니다. 꼭 참고하시고 원인모를 에러를 만나 쓸데없이 디버깅하는 시간을 최대한 줄여봅시다.


인라인 함수


C++ 에서는 길이가 짧은 함수의 성능 향상을 위해서 인라인 함수를 사용할 수 있습니다.


우리는 지난 시간부터 프로그램을 짤때 프로그램이 읽기 쉽고 유지보수도 좋아지게 하기 위해 함수를 사용하고 있습니다. 


그러나 함수 호출은 어떻게든 메모리를 잡아먹습니다. 


책에는 되게 어려운말이 쓰여있는데 제 식대로 해석하자면 프로그램이 처리할 내용이 많아지면서 컴퓨터에 부하가 걸린다는 내용으로 해석해도 충분할것 같습니다.


그래서 이런 가벼운 함수를 사용해야할때 저런 패널티를 피하고자 인라인 함수를 사용할수 있습니다. 


인라인 함수는 함수처럼 호출되는 것이 아니라 컴파일러에 의해 인라인 함수를 호출하는 지점에 함수 코드를 복사하는 방식입니다.


인라인 함수를 지정하기 위해서는 함수를 선언할때 inline 키워드를 붙이면 됩니다. 예제로 확인해봅시다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
 
inline void f(int month, int year)
{
    cout << "month is " << month << endl;
    cout << "year is " << year << endl;
}
 
int main()
{
    int month = 10, year = 2018;
    f(month, year); // 인라인 함수 호출
    f(92019); // 인라인 함수 호출
 
    return 0;
}
cs


코딩으로 보면 함수와 인라인함수의 차이는 앞에 inline이 붙냐, 안붙냐의 차이인데, 실제로는 컴파일러가 인라인 함수를 호출하는 지점에서 인라인 함수 코드를 복붙하여 코드가 확장됩니다.


따라서 위의 예제는 아래 예제와 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
 
int main()
{
    int month = 10, year = 2018;
    cout << "month is " << month << endl;
    cout << "year is " << year << endl;
    cout << "month is " << 9 << endl;
    cout << "year is " << 2019 << endl;
 
    return 0;
}
cs


인라인 함수를 사용할 때 주의할 점은 함수의 길이가 짧은 경우에는 인라인 함수를 사용하는것이 적합하지만, 프로그램의 여러곳에서 호출되는 긴 함수의 경우에는 적합하지 않습니다.


왜냐하면 길이가 긴 인라인 함수가 호출 시점으로 복사되는 형태이기 때문에 결과적으로는 프로그램 전체 코드의 크기가 커지는 현상이 발생할 수 있기 때문입니다.


이러한 이유로, C++에서는 함수가 긴 경우에 컴파일러가 자체적으로 inline 키워드를 무시할수 있습니다.


그러므로 inline 키워드는 단지 함수를 인라인 함수로 처리해달라고 컴파일러에게 부탁하는 꼴이고 실제로 처리할지 말지는 컴파일러가 결정합니다.


지역변수 , 전역 변수, 정적 지역변수


저번 강의중에 변수에 대해서 설명할 때, 간단하게 지역변수와 전역변수에 대해 알아보았습니다. 그 심화의 내용입니다.


변수의 범위는 변수가 참조될 수 있는 프로그램의 영역을 말합니다.


함수 안에서 정의된 변수를 지역변수라고 합니다.


한마디로 함수 블록 안에, 반복문 블록 안에, 선택문 블록 안에 선언되면 그것이 그 함수, 반복문, 선택문의 지역변수가 됩니다.


반면, 모든 함수 외부에서 선언되어 파일 내 모든 함수에서 접근이 가능한 변수를 전역변수라고 합니다.


간단하게 프로그램 어디서든지 쓸수있는 변수가 바로 전역변수입니다.


지역변수는 기본값이 없지만, 전역변수는 기본값이 항상 0이다. 따로 초기화를 하지 않아줘도 자동으로 0으로 초기화 됩니다.


변수는 사용하기전에 무조건 먼저 선언되어 있어야 하며, 지역변수의 범위는 선언한 지점으로부터 그변수가 포함된 해당 블록 끝까지입니다.


전역변수의 범위는 변수를 선언지점으로부터 프로그램 끝까지입니다.


이것만 알아도 지역변수와 전역변수의 차이를 확실하게 각인할 수 있습니다.



함수 실행이 완료되면 모든 지역변수는 메모리에서 사라집니다. 이런 변수들을 자동변수라고 합니다. 자동으로 날라가서 자동변수입니다.


그러나 때로는 다음번 호출 시에 지역변수를 다시 사용하기위해서 지역변수에 저장된 값을 유지하고 싶어질 때가 있습니다.


이럴때 우리에게 필요한 변수가 정적 지역변수입니다.


정적 지역변수는 프로그램이 끝날 때까지 메모리에서 사라지지 않고 계속 유지되는 변수입니다.


정적 지역변수를 선언하려면 static 키워드를 사용합니다.


예제로 알아봅시다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
 
void t1(); // 함수 프로토타입
 
int main()
{
    t1();
    t1();
 
    return 0;
}
 
void t1();
{
    static int x = 1;
    int y = 1;
 
    x++;
    y++;
    cout << "x is " << x << endl;
    cout << "y is " << y << endl;
}
cs


결과:

1
2
3
4
x is 2
y is 2
x is 3
y is 2
cs


예제의 16행에서 변수 x 는 정적 지역변수로 선언되었고, 변수 y는 지역변수로 선언되었습니다.


예제의 출력결과를 보면 정적 지역변수의 특징을 알 수 있습니다.


먼저 함수 t1()의 첫번째 출력은 x = 1, y =1 에 각각 1씩 더한 2, 2 가 됩니다.


두번째 출력에서 정적 지역변수가 힘을 발휘합니다.


원래대로면 함수가 한번 출력되면서 메모리상의 x 값과 y 값이 날라가고 2로 초기화 되어 다시 2, 2 를 출력해야 하지만, 변수 x는 정적 지역변수입니다.


그렇기 때문에 메모리에서 저장된 값이 날라가지 않고, 값이 남아있게 되어 2 + 1 인 3이되어 출력됩니다.


계속 함수를 호출하면 y는 계속 2로 출력되지만, x는 호출한 만큼 값이 더해져서 출력됩니다.


이것이 정적 지역변수의 특징입니다.



원래 이 뒤에 잠조에 의한 전달, 상수참조 매개변수, 함수 추상화와 단계적 상세화 등등 많은 심화내용이 존재합니다만, 저는 그런 어려운 내용을 다루지 않겠습니다.


너무 어려운것은 배움의 의지를 꺾어놓기 때문입니다.


그리고 이거부터 이해하지 못하면 그뒤 심화를 배워도 소용이 없습니다. 완벽히 이해한 후 찾아보는것도 나쁘지 않습니다.


오늘의 숙제입니다. 


메인함수가 없는 자기만의 함수 프로그램을 짜보세요! 아이디어가 없어도 괜찮습니다. 굉장히 간단한 내용이어도 상관없습니다. 


함수프로그램을 3개이상 작성하고나면 메인함수와 어떻게 이어야 할지 대충 감이 오실겁니다. 그게 숙제입니다.


어떤 프로그램을 작성했는지 댓글로 달아주세요! 칭찬해드리겠습니다 ㅋㅋㅋㅋㅋㅋ


함수는 이렇게 마무리하겠습니다. 다음 시간에는 배열에 대해서 알아보겠습니다.

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함