1. default parameter
- 함수 호출 시 인자를 전달하지 않으면 미리 지정된 인자값을 사용할 수 있다.
void move(int x, int y = 0, int z = 0) {
}
int main() {
move(1, 2, 3);
move(1, 0, 0);
move(1); // 1, 0, 0
move(1, 10) // 1, 10, 0
}
- 함수의 마지막 인자부터 차례대로 디폴트 값을 지정해야 한다.
void move(int x = 0, int y) { } // error
int main() {
move(3); // y에 3이 적용될 것인가?
}
//----- 예시 ------
void t1(int a, int b, int c = 0) { } // ok
void t2(int a, int b = 0, int c = 0) { } // ok
void t3(int a = 0, int b = 0, int c = 0) { } // ok
void t4(int a = 0, int b, int c ) { } // error
void t5(int a = 0, int b, int c = 0) { } // error
void t6(int a, int b = 0, int c ) { } // error
- 함수를 선언과 구현으로 분리 할 때는 함수 선언부에만 디폴트 값을 표기해야 한다.
void main(int x, int y);
int main() {
move(1, 2); // ok
move(1); // 인자가 두개인데 하나만 보냈으니 error
move(); // 마찬가지 이유로 error
}
void move(int x = 0, int y = 0) {
}
- 위의 코드에서 구현부에서 default로 정한 인자를 선언부에 적으면 error를 없앨 수 있다.
2. function overloading
- C언어에서는 동일한 이름의 함수를 2개 이상 만들 수 없다.
- C++언어 에서는 동일한 이름의 함수를 여러 개 만들 수 있다.
=> 단, 함수 호출 시 구별할 수 있도록, 인자의 개수나 인자의 타입이 달라야 한다.
- 함수 사용자 입장에서는 동일한 함수처럼 생각하게 되므로 일관된 형태의 라이브러리를 구축할 수 있다.
- C언어를 제외한 대부분의 최신 언어들이 지원하는 특징(Java, C++, C#, Swift 등)
int rect(int a, int b) {
return a * b;
}
double rect(double a, double b) {
return a * b;
}
int main() {
rect(1, 2); // 위의 함수를 호출
rect(3.4, 5.6); // 아래의 함수를 호출
}
- 인자의 개수가 달라도 디폴트 값이 있는 경우는 주의 해야 한다.
- 함수 반환 타입만 다른 경우는 오버로딩 될 수 없다.
- 정수타입과 포인터 타입에 대한 오버로딩은 에러는 없지만 사용하지 않는 것이 좋다.
void t1(int a) { }
void t1(double a) { } // ok
void t2(int a) { }
void t2(int a, int b) { } // ok
void t3(int a) { }
void t3(int a, int b = 0) { } // error
//t3(10); - 둘 중 무슨 함수를 호출해야 할지 모른다.
int t4(int a) { return 0; }
double t4(int a) { return 0; } // error
//t4(10); - 반환 타입만 다른 경우 무엇이 호출 될 지 몰라 error
void t5(int n) { }
void t5(char* s) { } // ok 이긴 하지만... 가독성이 떨어짐
//t5(0); - 포인터 변수를 초기화할 때 0을 쓸수도 있지만, 0은 정수이므로 int n으로 호출됨
//t5((char*)0); - 아래함수를 부를 수 있음
//t5(nullptr); - 아래 함수를 부를 수 있음 C++11부터 사용가능
3. template
- 타입만 다르고 구현이 동일하거나 유사한 함수가 여러개 있다면 직접 만들지 말고, 컴파일러가 함수를 생성하게
- 컴파일러가 함수를 생성할 때 사용할 함수의 틀(template)이 있어야 한다.
- 개발자는 함수 템플릿을 만들고, 컴파일러가 템플릿을 사용해서 필요한 함수를 생성하게 한다.
template<typename T> // 틀을 만듬. T대신 다른 문자를 넣어도 되지만 관례상 T를 많이 씀.
T rect(T a, T b) {
return a * b;
}
/*
double rect(double a, double b) {
return a * b;
}
*/
int main() {
rect<int>(1, 2); // int rect(int a, int b)
rect<double>(3.4, 5.6); // double rect(double a, double b)
}
- 함수가 아닌 함수를 만드는 틀(template)
- 템플릿을 사용하는 코드를 보고 컴파일러가 컴파일 시간에 필요한 타입의 함수를 생성
- 컴파일 된 기계어 코드에는 int, double 버전의 rect 함수가 따로 존재
//template<class T>
template<typename T> // template parameter
T rect(T a, T b) { // call parameter
return a * b;
}
int main() {
rect<int>(1, 2);
rect<double>(3.4, 5.6);
rect(1, 2);
rect(3.4, 5.6);
}
3.1 template parameter
=> 컴파일 시간에 전달되어서 함수가 생성
=> 함수가 생성되는 과정을 템플릿 인스턴스화(tempate instantiation)이라고 한다.
3.2 call parameter
=> 실행시간에 함수에 전달
- template parameter를 표기할 때 typename 또는 class 키워드 사용가능 (요즘은 typename 사용 추세)
- 함수 템플릿 사용시 타입을 명시적으로 지정하지 않으면 함수 호출 인자를 보고 컴파일러가 결정(type deduction, 추론/연역)
template<typename T>
struct Point {
T x;
T y;
};
int main() {
Point<int> pt;
pt.x = 1;
pt.y = 1;
Point<double> pt2;
pt2.x = 1.2;
pt2.y = 3.4;
}
3.3 클래스(구조체) 템플릿
- 함수 뿐 아니라 클래스(구조체)도 템플릿으로 만들 수 있다.
- C++17 부터는 생성자가 있으면 템플릿 파라미터 전달을 생략할 수 도 있다.
4. inline function
- 함수 반환 타입 앞에 inline을 표기한 함수
- 함수 호출 시 함수로 이동하지 않고 함수의 기계어 코드를 치환 한다.
- 장점
=> 실제 함수 호출 보다 빠르다.
- 단점
=> 치환되는 함수가 큰 경우 목적 코드가 커질 수 있다.
int add1(int a, int b) {
return a + b;
}
inline int add2(int a, int b) {
return a + b;
}
int main() {
int n1 = add1(1, 2); // 호출
int n2 = add2(3, 4); // 치환
}
4.1 컴파일러와 인라인
- 어셈블리 소스 코드를 확인 하는 방법
=> cl 컴파일러 : cl 소스이름.cpp /FAs -> 소스이름.asm
=> g++ 컴파일러 : g++ 소스이름.cpp -S -> 소스이름.s
- 인라인 함수의 실제 치환 여부는 컴파일러 종류, 컴파일 옵션, 함수 크기등에 따라 달라진다.
=> cl 컴파일러의 경우는 /Ob1 옵션 사용 시 치환 적용
=> g++은 -fno-inline , -finline-small-functions , -findirect-inlining 등 수많은 옵션이 존재
- 호출의 경우 5줄의 코드가 나옴 (push ~ mov)
- 치환은 2줄 (move ~ add)
- 작은 함수는 치환이 목적 코드를 줄일 수 있다.
'프로그래밍 > C++' 카테고리의 다른 글
[C++] range for / if init / if constexpr (0) | 2019.10.18 |
---|---|
[C++] C언어와 다른 C++ 함수(2) (0) | 2019.10.11 |
[C++] 변수(2) (0) | 2019.10.05 |
[C++] 변수(1) (0) | 2019.10.05 |
[C++] iomanipulator (0) | 2019.10.05 |