[따배씨++]Chapter7-2. 함수
카테고리: Cpp
태그: Programming
인프런에 있는 홍정모님의 홍정모의 따라하며 배우는 C++ 강의를 듣고 정리한 내용입니다.
공부하는 식빵맘 님의 블로그를 참고했습니다.
🚆 함수 오버로딩
함수의 이름 중복 사용. 시그니쳐로 구분
void getRandom(int& x);
void getRandom(double& x);
- 시그니처란 변수의 타입, 변수의 갯수
- 리턴 타입은 시그니처 아님!
- 어떤 함수가 호출될지는 컴파일 타임에 결정되어야 함
void print(unsigned int value);
void print(float value);
void print(const char* value);
int main()
{
print(0); // Error
print('a'); // Error
print(3.14); // Error
print(0u); // OK
print((unsigned int)'a'); // OK
print("a"); // OK
print(3.14f); // OK
return 0;
}
- 애매하면 컴파일러가 구분 못함
- 오버로딩 사용 시에는 타입 명시해주는게 안전
- char은 int로 넘어가네..
🚆 기본 값 설정 - Default Parameters
int func_1(int x = 1, int y = 1, int z = 2) {}; // OK
int func_2(int x, int y, int z = 2) {}; // OK
int func_3(int x = 1, int y, int z) {}; // Error
- 기본 값이 없는 변수는 왼쪽에 있어야 함
- 선언 & 정의 나눌 시 둘 중 한 곳에서만 기본값 설정
- 보통은 헤더파일에 선언하면서 기본 값 설정
🚆 함수 포인터
함수도 메모리 주소 갖고 있다 → 포인터 사용 가능
int func(int x)
{
return x;
}
int main()
{
cout << func << endl; // 00007FF72CAD143D 출력 (함수의 주소)
int(*funcptr)(int) = func;
cout << funcptr(5) << endl; // 5 출력
return 0;
}
문법 : (리턴타입)(*포인터 이름)(파라미터) = 함수
funcptr = func2
- 포인터는 다른 함수 지정할 수도 있음
- 리턴 타입, 파라미터 타입, 파라미터 갯수 같아야 함
함수 포인터 예시 - 사용 전
void printNumbers(const array<int, 10>& my_arr, bool print_even)
{
for (auto element : my_arr)
{
if (print_even && element % 2 == 0) cout << element;
if (!print_even && element % 2 == 1) cout << element;
}
cout << endl;
}
int main()
{
std::array<int, 10> my_arr{ 0,1,2,3,4,5,6,7,8,9 };
printNumbers(my_arr, true); // 짝수 원소만 출력
printNumbers(my_arr, false); // 홀수 원소만 출력
return 0;
}
- 버튼 (true/false, 0/1/2/…)을 만들어 각각 기능 구현
함수 자체를 파라미터로 넘기기 - 사용 후
bool isEven(const int& number)
{
if (number % 2 == 0) return true;
}
bool isOdd(const int& number)
{
if (number % 2 == 1) return true;
}
void printNumbers(const array<int, 10>& my_arr, bool(*check_func)(const int&))
{
for (auto element : my_arr)
{
if (check_func(element) == true) cout << element;
}
cout << endl;
}
int main()
{
std::array<int, 10> my_arr{ 0,1,2,3,4,5,6,7,8,9 };
printNumbers(my_arr, isEven); // 짝수 원소만 출력
printNumbers(my_arr, isOdd); // 홀수 원소만 출력
return 0;
}
함수 포인터 사용 TIP
1. using
using check_func_t = bool(*)(const int&);
check_func_t funcptr = isEven;
2. typedef
typedef bool(*check_func_t)(const int&);
check_func_t funcptr = isEven;
3. std::function
std::function<bool(const int&)> funcptr = isEven;
#include \<functional>
: C++11에 추가문법 : std::function<리턴타입(파라미터)> 변수 이름 = 함수
- 함수 포인터 대신 function 기능도 많이 쓴다고 함
🚆 스택 vs 힙
Stack
- 빠름
- 사이즈 작음
- 큰 메모리를 차지하는 변수 (ex. array[1000000])나 많은 재귀 호출시 Stack Overflow
- 차곡차곡 메모리 할당/해제
Heap
- 사이즈 큼
- OS가 개입하기 때문에 느림
- 어디에 위치할지 알기 어려움
- OS가 쭉 둘러보고 연속적인 메모리 할당할 수 있으면 그곳에 메모리 할당
- 메모리 해제 안해주면 누수 발생
🚆 std::vector 심화
Size 와 Capacity
capacity
- 벡터가 실제 차지하는 메모리 공간
size
- capacity 중 실제 벡터가 사용하는 공간
- size 넘어가는 공간은 접근 불가 (vector.[end] // error)
- capacity보다 작은 사이즈로 resize할 시 delete/new 안 함
- capacity보다 큰 사이즈로 resize 하면? → delete/new
vector.reserve(1024)
- capacity 확보만!
- 성능차이 확실히 남~
vector를 스택처럼 사용하기
넉넉하게 reserve 하고 벡터를 스택처럼 사용하면 더 빠름!
- vector.push_back() - Stack.push
- vector.pop_back() - Stack.pop
🚆 Assert - 단언하기
일일이 찍어보기 귀찮을 때 사용하는 디버깅을 위한 함수 release 모드에서는 작동 안 함
#include <cassert>
assert(조건)
- 조건식이 false이면 런타임 에러 발생
- 디버그 모드 실행 시 어디에서 assert error가 났는지 찍어줌
static_assert(조건)
- 조건식이 false이면 컴파일 에러 발생
- 컴파일 타임에 결정되는 조건식만 넣어야 함
🚆 생략 부호 - Ellipsis
double findAverage(int count, ...){};
- 파라미터의 타입과 개수 생략 가능
- 주의) 여러가지 문제가 발생할 수 있음
- 컴파일러가 Type checking을 안 함
- ex)
findAverage(6, 1.0, 2, 3, 4, 5) → 1.78782e+008
- 중간에 double 끼어서 이상한 값이 출력되지만 컴파일러가 체크를 안 함
- 가능하면 사용하지 말자
- 동적 할당을 이용해서 파라미터 넘기면 피할 수 있음
댓글 남기기