Chapter6: 함수 part2

Joosi_Cool·2022년 6월 29일
3

C++

목록 보기
7/20
post-thumbnail

🐣 함수 part2

기본 매개변수

기본 매개변수란, 매겨변수 값에 기본값을 부여하는 것이다.
int print(int a, int b=1); 이런식으로 선언이 가능하다.

#include<iostream>
using namespace std;

void print(int a = 1, int b = 2, int c = 3);
void print2(int a, int b , int c = 3);

int main() {

	print(5);
	print(5, 6);


	print2(5, 6);
	print2(5, 6, 7);

	return 0;

}


void print(int a, int b, int c) {
	cout << a << " " << b << " " << c << endl;
}

void print2(int a, int b, int c) {
	cout << a << " " << b << " " << c << endl;
}

위의 코드를 기준으로 설명을 하면 print함수에 경우 a,b,c에 기본값을 정해주었다. 인자의 경우 왼쪽을 가장 먼저 대입시킨다. 그래서 print(5)의 경우, a의 5를 대입하고 나머지는 정해주지 않았기 때문에 기본값이 출력된다.


기본 매개변수를 지정해줄때는 오른쪽부터 정해주어야 한다. 그 이유는 왼쪽부터 인자가 들어가는데, 오른쪽부터 지정해주지 않는다면 오류가 생길 것이다. print2함수의 경우로 예시를 들어보자. print2(5,6)을 진행했을때, a에는 5. b에는 6이 대입된다. c는 받은 값이 없기 때문에 기본값이 출력된다. 만약 오른쪽부터 채우지 않았다면? b에만 기본값을 줬다면? c에는 들어가는 값이 없기 때문에 오류가 발생한다.
따라서 인자는 왼쪽부터 들어가고, 매개변수는 오른쪽부터 만들어줘야 한다.

함수 오버로딩

이름이 같은 함수를 2개 정의할 수 있을까? => 가능하다.


함수오버로딩이란, 이름은 같지만 매개변수의 자료형, 개수, 순서를 다르게 하여 정의하는 것을 말한다. 이는 컴파일러가 함수 시그니처를 통해 구분할 수 있다. 이 함수 시그니처는 함수이름+매개변수 목록을 말한다. 단, 리턴 타입은 이에 해당하지 않는다.

#include<iostream>
using namespace std;

int sum(int a, int b);
int sum(int a, int b, int c);

int main() {

	cout << sum(1, 2) << endl;
	cout << sum(1, 2, 3) << endl;
	
	return 0;

}

int sum(int a, int b) {
	return a + b;
}

int sum(int a, int b, int c) {
	return a + b + c;
}

위의 코드처럼 같은 이름의 함수를 매개변수의 자료형, 개수, 순서를 다르게 하여 나타내는 함수 오버로딩이 가능하다.

함수 오버로딩을 사용할때, 모호한 상황이 나타나 에러가 발생할 수 있다. 모호한 상황이란, 오버로딩 된 함수들 중에서 뚜렷하게 어떤 함수를 써야될지 인지를 못하는 상황이다. 함수오버로딩 된 것 중에 입력된 인자에 맞는 함수를 찾는데, 없다면 암시적 형변환을 통해서 찾으려 한다. 이때 여러가지 함수에 해당되면 이때 에러가 발생할 수 있다. 아래 코드가 그 예시이다.

#include<iostream>
using namespace std;

int sum(int a, double b);
int sum(double a, int b);

int main() {

	cout << sum(1, 2.5) << endl; //1번 함수 사용
	cout << sum(2.5, 1) << endl; //2번 함수 사용
	
	//암시적 형변환을 한다면 위의 두 함수 모두 사용가능 어떤걸 사용?
	cout << sum(1, 2) << endl; //?

	return 0;

}

int sum(int a, double b) {
	return a + b;
}
int sum(double a, int b) {
	return a + b;
}

지역변수 vs 전역변수 vs STATIC

  • 스코프란?
    => 어떤 엔티티(상수, 변수, 객체, 함수 등)를 사용할 수 있는 범위를 말한다.
  • 지역변수 (자동 지역 변수) => 지역 안에서만 사용 가능, 함수가 호출될 때 생성되고 종료될때 사라진다.
  • 전역변수 => 전역에서 사용 가능, 이는 코드가 끝날 때까지 계속 남아있다.
  • static (정적 지역 변수) => 지역 안에서만 사용 가능, 메모리 상으로는 데이터 값 남아있다.
#include<iostream>
using namespace std;

void  useLocal();
void useStaticLocal();
void useGlobal();

int x{ 1 };

int main() {
	
	//지역변수
	useLocal();
	useLocal();

	//static 변수
	useStaticLocal();
	useStaticLocal();
	
	//전역변수
	useGlobal();
	useGlobal();

}


void useLocal() {
	int x{ 25 };

	cout << "지역 변수 x = " << x << endl;
	x++;
	cout << "1을 더한 지역 변수 x = " << x << endl;
}

void useStaticLocal() {
	static int x{ 50 };

	cout << "스태틱 변수 x = " << x << endl;
	x++;
	cout << "1을 더한 스태틱 변수 x = " << x << endl;
}

void useGlobal() {
	
	cout << "전역 변수 x = " << x << endl;
	x*=10;
	cout << "10을 곱한 스태틱 변수 x = " << x << endl;

}

위의 코드를 분석해보자.
useLocal(): 지역변수 함수인데, 이는 결과를 보면 값이 저장되지 않는 것을 알 수 있다.
useStaticLocal(): static 변수 함수로서, 값이 계속해서 저장되는 것을 볼 수 있다.
useGlobal: 전역 변수 함수로서, static과 마찬가지로 계속해서 값이 저장된다. 전역변수와 static변수의 차이로는 전역변수는 전역에서 사용할 수 있지만, static변수는 그 지역 안에서만 사용 가능하다.

Inline

이는 함수를 호출할 때, 그 코드를 함수 대신에 같다 붙이는 것이다. 함수가 호출될 때 인자를 받고, 함수로 가기전에 어디서부터 시작해야 되는지 Return-Address를 받고 매개변수를 저장한다. 함수를 호출하는 시점에 이러한 함수 프레임이 발생한다.


간단한 코드의 경우, inline은 함수 내부에서 계산하는 것이 아니라 바로 함수를 가져다 쓰는 것을 추천한다. 이 추천이라는 점은 어떤 것이 효율적인지 컴퓨터가 판단하여 inline을 쓸지 안쓸지 결정한다.


쓰는 방법은 함수 앞에 inline을 붙이면 된다. ex) inline double examaple(const double side);
하지만 요즘 컴퓨터는 inline을 굳이 붙이지 않아도 알아서 판단하여 적용하기 때문에 할 필요는 없다.

재귀

재귀란, 함수 안에서 함수를 불러서 계속 반복적으로 실행하는 것을 말한다. 말로는 어려우니 코드로 예시를 들겠다.

#include<iostream>
using namespace std;

int factorial(int num);


int main() {

	cout << "7! = " << factorial(7) << endl;

}


int factorial(int num) {

	if (num <= 1) {
		return 1;
	}

	return factorial(num - 1) * num;

}

이처럼 함수 안에서 이전의 함수를 불러오는 것을 반복하는 방식이다. 이것이 구현되기 위해서는 두가지 조건이 필요하다.
1. 문제를 줄여나갈 수 있어야 한다.
2. base case => 끝나는 지점이 있어야 한다.

profile
집돌이 FE개발자의 노트

0개의 댓글