[따배씨++]Chapter7-2. 함수

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모님의 홍정모의 따라하며 배우는 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

cpp9_1

  • 빠름
  • 사이즈 작음
    • 큰 메모리를 차지하는 변수 (ex. array[1000000])나 많은 재귀 호출시 Stack Overflow
  • 차곡차곡 메모리 할당/해제


Heap

cpp9_2

  • 사이즈 큼
  • OS가 개입하기 때문에 느림
  • 어디에 위치할지 알기 어려움
    • OS가 쭉 둘러보고 연속적인 메모리 할당할 수 있으면 그곳에 메모리 할당
  • 메모리 해제 안해주면 누수 발생


🚆 std::vector 심화

Size 와 Capacity

cpp9_3

  • 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

learncpp.com 참고자료

double findAverage(int count, ...){};
  • 파라미터의 타입과 개수 생략 가능
  • 주의) 여러가지 문제가 발생할 수 있음
    • 컴파일러가 Type checking을 안 함
    • ex) findAverage(6, 1.0, 2, 3, 4, 5) → 1.78782e+008
    • 중간에 double 끼어서 이상한 값이 출력되지만 컴파일러가 체크를 안 함
  • 가능하면 사용하지 말자
    • 동적 할당을 이용해서 파라미터 넘기면 피할 수 있음



맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기