본문 바로가기

프로그래밍/C++ language

6. 함수(function)

- 함수는 코드를 재사용하고, 조직화하고 간략화 하기위해 사용함

 

6.3 함수 호출

 

- 함수는 호출 될 때마다 argument와 variable을 저장하는 activation record(= activate frame)을 생성하고, 그것을 call stack에 저장함

- main함수가 max함수를 호출했다면, main함수의 activation recore가 stack에 저장되고, 그 위에 max함수의 것이 저장됨 (LIFO구조)

 

6.7 함수 오버로딩(function overloading)

 

- 함수 이름은 같지만, 매개변수가 다른 함수를 작성하는 것(반환유형만 다른경우x)

- 실행시 오버로딩된 함수들 중 가장 가까운 함수를 호출함

- 두 함수중 어느것을 호출해야할지 compiler가 결정하지 못할 경우 ambiguous invocation이라고함(컴파일 오류)

- 결과적으로 같은

 

ex)

int max(int num1, int num2){

...

} //첫번째 함수

double max(double num1, double num2){

...

} //두번째 함수

// max(3, 4)를 실행했을 때 가장가까운 함수인 첫번째 함수를 호출한다.

// max(3.5, 4.5)를 실행했을 때 가장가까운 함수인 두번째 함수를 호출한다.

// max(3, 3.5)를 실행했을 경우, 둘중에 가까운 것을 찾지 못해서 오류발생(ambiguous invocation)

 

6.9 기본인수(default argument)

 

- argument가 생략된채로 작성된 함수 호출에 대해서, default값이 설정되어있다면 default값이 parameter로 전달됨

- 이것은 function declaration부분에 작성되어야 함

- default값이 들어간 argument 부분은 argument list의 맨 뒷부분에 존재해야함

 

ex1) void point(int x, int y = 0, int z = 0); //function declaration

point(0); // 0, 0 ,0

point(0, 1); // 0, 1, 0

point(0, 1, 2); // 0, 1, 2

void point(int x, int y, int z){

...

} //function definition

 

ex2) void point(int x, int y = 0, int z); //error발생

 

6.10 인라인 함수(inline function)

 

- 함수 호출이 빈번하게 발생하는 것을 피하기 위해, inline function을 통해 사용된 정의된 함수는 컴파일과정에서

정의된 함수코드로 내부적으로 code substitution이 됨, 따라서 함수호출이 일어나지 않음

- macro substitution과 같이 정의가 호출이전에 나와있어야됨. 따라서, header파일로 만들어 정의된 것이 좋음.

- macro에서 text substitution과 다른 것은, macro substitution은 컴파일 이전에 전처리기(preprocessor)과정에서 일어남

또한, type형에 대한 검사를 하지 않음

- 긴 함수에 대해서 이것을 자주 시도할 경우, 코드가 길어져 프로그램의 크기가 커지는 문제가 발생함

- 최신 compiler는 프로그래머가 inline을 요구하여도 코드가 너무 길어질 경우 실제로 inline하지 않고,

inline을 표기하지 않아도 스스로 판단하여 inline함

 

ex)

#define sum(x,y) = (x + y) // macro substitution

inline int sum(int x,int y){

return (x+y);

} // inline function

 

6.11 local variable, global variable, static local variable

 

- local variable, static local variable은 함수 내에 선언

- global variable은 함수 외부에 선언

 

- local variable의 scope는 선언 이후부터, 함수를 나갈때까지(나가면 메모리에서 사라짐)

- global variable의 scope는 선언 이후부터, 프로그램이 끝날 때까지

- static local variable의 scope는 선언 이후부터, 함수를 나갈 때까지(나가도 메모리에 유지됨, 첫 호출시에만 초기화)

- for문 초기에 선언된 변수는 for문 내부가 scope임

 

ex) int i;

int main(){

int j;

cout << i << endl; /

cout << j << endl;

}

 

6.12 참조에 의한 전달(pass-by-reference)

 

- 함수의 argument전달은 기본적으로 pass-by-value의 형태로 이루어짐, 즉 값이 복사되어 들어감

- &(ampersand)를 사용하여 전달할 경우, 해당 변수를 참조하는 주소가 전달됨

- &를 통해 선언된 변수인 reference는, 주소가 동일하다는 뜻이므로 참조되는 변수의 alias(별명), 즉 완전히 동일함

 

- pointer와의 차이점은 pointer는 주소값을 저장할 공간이 필요하지만, reference는 필요 없음

- pointer는 null pointer가 가능하지만(유효성검사 필요), reference는 대상 객체가 반드시 존재해야함

- pointer는 주소'값'이므로, 언제나 변경가능하지만 reference는 불가능

- class member접근시 pointer는 주소에서 접근하므로 ->, reference는 원본에서 접근하므로 . 사용

 

ex1)

int main(){

int n1 = 1;

int n2 = 2;

swap(n1, n2);

}

void swap(&num1, &num2){

...

} //num1과 num2의 주소가 전달되어 return이 없어도 n1, n2가 변경됨

 

ex2)

int n1 = 1;

int &n2 = n1; //n2의 주소가 n1과 같다. 즉, n1과 n2는 동일한 것을 가리킴(aliasing)

n1 = 10;

cout << n1 << " " << n2 << endl; // 10 10 출력

n2 = 20;

cout << n1 << " " << n2 << endl; // 20 20 출력

 

6.13 상수 참조 매개변수(constant reference parameter)

 

- 함수 내에서 값이 변경되지 않는 큰 객체를 함수에 전달 할 때, 메모리 절약을 위해 사용

- 값이 변경되지 않는 동일한 객체를 두개의 stack에 저장하는 것은 overhead를 발생시킴

따라서, reference만을 전달하고 const를 이용하여 그것을 변경할 수 없게하면 메모리를 절약할 수 있음

- 이것은, 큰 객체가 아닌 primitive type인 int, double과 같은 것들을 함수에 전달할 때는 덜 효과적

 

ex)

int max(const int& num1, const int& num2){

...

} //num1, num2는 함수내에서 변경 불가능

int max(int num1, int num2){

...

} //num1, num2는 함수내에서 변경 가능

 

6.14 함수 추상화(function abstraction)와 단계적 상세화(stepwise refinement)

 

- function abstraction는 함수는 어떤 기능을 하는 추상적인 것이며

내부가 어떤식으로 구현되어 있는지 알필요 없이 사용할 수 있다는 개념

- 프로그램을 개발할 때 stepwise refinement를 하게 되는데, divide&conquer 방법을 사용할 수 있음

즉, 큰 문제를 작은 문제로 나누어 상세화하고 풀어나가는 것

이 때, function abstraction개념에 따라 구체적인 구현은 무시하고 추상적으로 문제를 분해해 나감으로서

stepwise refinement를 할 수 있음

- 문제를 구조화하여, top-down design(stub사용), bottom-up design(driver사용)등 가능