함수
하나의 작은 목적을 수행하기 위해 여러 문장을 모아 놓은 것
// 함수 헤더
returnValueType functionName(list of parameters)
{
// 함수 몸체 : 할 일 정의
}
// 함수 호출 : 함수 사용
functionName(actual parameter);
* 함수 헤더 : 함수의 반환값 유형(returnValueType), 함수 이름(functionName), 매개변수로 구성
** 매개변수 : 함수 헤더에 작성된 변수. 함수가 호출될 때 값이 전달되어 저장되는 변수
** 실매개변수(인수) : 호출하는 쪽의 매개변수
함수의 특징
5 int max(int num1, int num2)
6 {
7 int result;
8
9 if(num1 > num2)
10 result = num1;
11 else
12 result = num2;
13 return result;
14 }
15
16 int main()
17 {
18 int i = 5;
19 int j = 2;
20 int k = max(i, j);
21
22 cout << "the maximum between" << i << "and" << j << " is" << K;
23 // cout << max(i,j);
24
25 return 0;
26 }
결과 : the maximum between 5 and 2 is 5
해설 :
위 코드 프로그램 제어 순서 : 16 ~ 19줄 → 5 ~ 14줄 → 20 ~ 25줄
22번째와 같이 하나의 변수처럼 사용할 수도 있으며 23번째 줄과 같이 수식에서도 사용 가능하다
- 함수는 값을 반환한다 (O)
- 함수는 반환내용 없이 주어진 일을 처리한다 (O)
* void 함수 : 반환값이 없는 함수
** void 함수의 호출은 하나의 문장으로 작성해야 함, 즉 수식이나 대입 식에 void 함수를 포함시킬 수 없음
- 함수를 사용하면 프로그램이 읽기 쉽고 유지보수도 좋아진다.
- 그러나 함수 호출은 실행 오버헤드(인수전달, cpu 레지스터를 스택으로 이동, 함수간의 제어 전달, context switch overhead 등)가 발생
- 프로그램에서 함수를 호출하게 되면 프로그램 제어는 호출하는 함수 쪽으로 넘어간다. 호출된 함수에서는 반환 문이 실행되거나 함수의 끝에 도달했을 때 호출자에게 제어를 되돌려준다.
- main도 함수이나 프로그램을 시작하기 위해서 운영체제에 의해 호출된다는 점이 일반함수와 다르다.
- 함수는 호출되기 전에 선언되어야 한다.
→ 함수 호출 전 함수 원형 선언 필요
* 함수 원형(prototype);: 함수의 구현(몸체)이 없는 선언
- 함수 원형에서는 매개변수의 이름을 작성할 필요는 없고 매개변수 유형만 있어도 된다.
* 함수 시그니처 : 함수이름, 매개변수
** 반환 타입은 함수 시그니처 아님!
o 인라인 함수
함수처럼 호출되는 것이 아니라 컴파일러에 의해 인라인 함수를 호출하는 지점으로 함수 내용을 복사하는 방식
- 함수 선언 앞에 inline 키워드 사용
- c++ 컴파일러가 인라인 함수를 호출하는 지점에 인라인 함수를 복사해 넣어 코드를 확장하는 것이다.
- 함수의 길이가 짧은 경우에만 적합, 여러 곳에서 호출되는 큰 함수의 경우 부적합
→ 인라인 함수로 처리할지 무시할지의 결정은 컴파일러에게 달려있다.
인수 전달 방법
매개변수가 있는 함수를 호출할 때 인수 값 전달
1) Call-by-value(값에 의한 전달)
인수가 변수라면 변수의 값이 매개변수로 전달됨
함수 안에서 매개변수의 값이 변경되더라도 호출한 곳에서 인수로 사용된 변수의 값은 변화가 없음
void increment(int n)
{
n++;
cout << "n inside the function is " << n << endl;
}
int main()
{
int x = 1;
cout << "before the call, x is " << x << endl;
increment(x);
cout << "after the call, x is" << x << endl;
return 0;
}
결과 :
before the call, x is 1
n inside the function is 2
after the call, x is 1
해설 :
함수 호출 후에도 함수의 값은 변하지 않는데(호출전, 후 값 모두 x는 1) 인수의 값이 매개변수로 전달되었기 때문이다. 이는 매개변수와 인수가 서로 독립적인 공간을 사용하기 때문에 인수의 값이 변경된다 해도 원 변수의 값은 변화가 없는 것이다.
- x를 n으로 이름을 바꾸면 어떻게 될까?
여전히 두 값의 변경은 이루어지지 않는다. 호출자의 인수와 함수의 매개변수가 같은 이름을 가진다 하더라도, 함수의매개변수는 함수가 호출될 당시에 호출자 인수와는 상관없이 자신만의 메모리 공간을 할당받는다. 이 매개변수를 위한 메모리 공간은 함수의 실행이 끝나고 호출자로 되돌아갈 때 사라지게 된다.
void swap(int n1, int n2)
{
cout << "Inside the swap function" << endl;
cout << "Before swapping n1 is" << n1 << "n2 is" << n2 << endl;
int temp= n1;
n1 = n2;
n2 = temp;
cout << "After swapping n1 is" << n1 << "n2 is " << n2 << endl;
}
int main ()
{
int num1 = 1;
int num2 = 2;
cout << "Before invoking the swap function, num1 is " << num1 <<
"and num2 is " << num2 << endl;
swap(num1, num2);
cout << "After invoking the swap function, num1 is "<< num1 <<
"and num2 is" << num2 << endl;
return 0;
}
결과 :
Before invoking the swap function, num1 is 1 and num2 is 2
Inside the swap function
Before swapping n1 is 1 and n2 is 2
After swapping n1 is 2 and n2 is 1
After invoking the swap function, num1 is 1 and num2 is 2
2) Call-by-reference(참조에 의한 전달)
o 참조변수
원 변수를 참조하기 위해 함수의 매개변수로 사용되는 변수
- 참조변수는 변수에 대한 별칭으로 동작하여, 참조 변수에 수정을 하면 원 변수에도 수정된 내용이 반영됨
- 참조변수를 선언할 때는 변수 앞에 엠퍼샌드&를 붙인다
type &ref_var;
ref_var = orgin_var;
→ type &ref_var = orgin_var;
int main()
{
int count = 1;
int &refCount = count;
refCount++;
cout << " count is " << count << endl;
cout << "refCount is" << refCount << endl;
return 0 ;
}
결과 :
count is 1
refCount 2
해설 :
함수 매개변수에서도 참조변수를 사용할 수 있으며 호출하는 측에서는 일반 변수를 사용하여 호출하면 된다. 이 때 매개변수는 원 변수에 대한 별칭이 된다.
* 즉, 다시한번 정리하면 함수에 매개변수를 전달하는 두가지 방법
- Call-by-value, Call-by-reference
- 값에 의한 전달은 독립적인 변수에 값을 복사하는 것이고, 참조에 의한 전달은 같은 변수를 공유하는 것
함수 오버로딩
하나의 파일 안에 이름은 같고 매개변수 목록만 다른 함수 여러 개 사용
- 함수 오버로딩은 프로그램을 보다 간결하게 하고 읽기 쉽게함
- 함수 호출 시 가장 가까운 함수를 찾음
* max(3, 4) : 3, 4가 int형이므로 max(double, double)보다는 max(int, int)를 호출
* max(1, 2) : max(int, double), max(double, int)이 있는 경우 모호한 호출 에러
→ 이름이 같되, 매개변수 목록이 달라야 함(반환 유형은 상관없음)
- 기본 인수 값으로 함수를 선언할 수 있는데, 인수없이 함수를 호출하면 기본 값이 매개변수로 전달된다.
- 함수의 장점 중 하나는 다른 프로그램에서 함수 재사용이 가능하다는 것이다.
- #include 전처리 지시자를 사용하여 함수를 포함한 프로그램의 헤더 파일을 포함시키면 된다.
- 헤더 파일에서 main 함수를 작성하지 말아야 한다.
지시자#
#: 컴파일하기 전에 ~부터 하라.
* #include <iostream> : 컴파일하기 전에 iostream 헤더파일을 인쿠르드하여라!
* 표기
- 표준 헤더 파일 : < >안에 표기,
- 사용자 정의 헤더 파일 : " " 안에 표기
지역변수와 전역변수
o 지역변수 : 함수 안에 선언된 변수
o 전역변수 : 함수 외부에서 선언되어 파일 내 모든 함수에서 접근이 가능한 변수
- 지역변수는 기본 값이 없지만, 전역 변수는 기본 값이 0으로 설정된다.
- 변수의 범위는프로그램에서 변수가 어떤 범위까지 참조되는 것인지에 관한 것으로 지역변수의 범위는 선언한 지점으로부터 해당 블록이 끝날 때까지이고, 전역변수의 범위는 변수 선언한 지점으로부터 프로그램이 끝날 때까지이다.
- 매개변수는 지역변수다.
* 변수는 사용하기 전에 먼저 선언되어 있어야함
int main()
{
t1();
t2();
return 0;
}
int y; // 전역변수, 초기값 0
void t1()
{
int x = 1; // 지역변수
cout << x <<" " << y << endl;
x++; y++;
}
void t2()
{
int x = 1;
cout << x <<" " << y << endl;
}
결과 :
1 0
1 1
해설 :
- t1()의 x와 t2()의 x는 이름만 같은 것이지 실제로 다른 메모리 영역에 저장되어 있기 때문에 서로 다른 변수이다. (t1의 x의 값의 변경이 t2의 x에 아무런 영향을 미치지 않음)
- 지역 변수의 이름과 전역 변수의 이름이 동일한 경우, 함수 내에서는 지역 변수의 이름만 접근할 수 있다.
→ 함수 내에서 전역 변수에 접근하고자 하는 경우에는 :: 전역변수 를 사용하여 전역변수에 접근할 수 있다.
* 정적 지역 변수
함수 실행이 완료되어도 사라지지 않는 지역변수
- static 키워드 사용
- 지역 변수를 사용하기 위해 지역변수에 저장된 값을 유지하고자 할 때 사용
- 프로그램이 끝날 때까지 메모리가 사라지지 않고 계속 유지된다.
void t1()
{
stiatic int x = 1; // 정적지역변수
int y = 1; // 지역변수
x++; y++;
cout << x << " " << y << endl;
}
※ 스택
메모리 영역. LIFO 형태
- 함수가 호출될 때마다 인수와 변수들을 스택 메모리 영역에 저장
- 함수가 다른 함수를 호출하면 현재 함수의 스택 공간은 유지되고, 호출된 함수를 위해 새로운 메모리 공간이 생성됨
'컴퓨터공학과 > Programming' 카테고리의 다른 글
[C++] 누구나 쉽게, 리팩토링(클린코드)-③ 캐스팅/형변환 종류 및 방법 (0) | 2020.04.08 |
---|---|
[C++] 누구나 쉽게, 리팩토링(클린코드)-② 인터페이스 (1) | 2020.04.07 |
[C++] 누구나 쉽게, 리팩토링(클린코드)-① 순수가상함수/추상클래스 (0) | 2020.03.25 |
[C++]정렬 알고리즘 프로그래밍-②정렬할 준비하기 (0) | 2020.03.25 |
[C++]정렬 알고리즘 프로그래밍-①코딩 준비하기 (0) | 2020.03.24 |