[따배씨++]Chapter7-1. 함수
카테고리: Cpp
태그: Programming
인프런에 있는 홍정모님의 홍정모의 따라하며 배우는 C++ 강의를 듣고 정리한 내용입니다.
공부하는 식빵맘 님의 블로그를 참고했습니다.
🚆 매개변수(Parameter) vs 인자(Argument)
void func(int x, int y) {}; // int x, int y : 매개변수 (paramater)
int main()
{
func(1, 2); // 1, 2 는 인자 (argument)
return 0;
}
- parameter는 함수 끝나면 os로 메모리 반납
🚆 인수 전달
Call by Value
void func(int x)
{
x = 20;
}
int main()
{
int a = 0;
func(a);
cout << a << endl; // 0 출력
return 0;
}
- 값이 복사되어 넘어감
- 함수 내에서 바꿔봐야 함수 끝나면 사라짐
Call by Reference
void func(int& x)
{
x = 20;
}
int main()
{
int a = 0;
func(a);
cout << a << endl; // 20 출력
return 0;
}
- 참조 변수는 메모리 공유
- 함수 내에서 변경한 값 유효함
포인터 참조
void func(int*& ptr)
{
cout << ptr << endl;
}
int main()
{
int x = 5;
int* ptr_x = &x;
func(ptr_x);
return 0;
}
typedef int* pint
지정하면 조금 덜 햇갈림- 함수 내에서 변경한 값 유효함
배열 & 벡터 참조
void func(int (&arr)[4])
{
for (auto& elements : arr)
cout << elements << endl;
}
void func(vector<int>& arr)
{
for (auto& elements : arr)
cout << elements << endl;
}
- 배열 참조시 사이즈 지정해줘야 함 (누가 쓰나..?)
call by reference 꿀팁
void getSinCos(double degrees, double& sin_out, double& cos_out)
{
static const double pi = 3.141592; // 자주 쓰는 값이면 static이 좋음
double radians = degrees * pi / 180.0;
sin_out = std::sin(radians); // #include <cmath>
cos_out = std::cos(radians); // #include <cmath>
}
int main()
{
double sin = 0.0, cos = 0.0;
getSinCos(30.0, sin, cos);
return 0;
}
- Reference input을 이용해 여러개의 output 효과를 낼 수 있음!
Call by Address
void func(int* ptr)
{
*ptr = 100;
}
int main()
{
int value = 5;
int* ptr_value = &value;
func(ptr_value); // OK
func(&value); // OK
func(5); // Error
return 0;
}
- 주소 자체는 복사하지만 같은 주소를 가리킴
- 함수 내에서 변경한 값 유효함
- R-Value는 못 넘어감
🚆 다양한 리턴 값
포인터 리턴
int* allocateMemory(int size)
{
return new int[size];
}
int main()
{
int* my_arr = allocateMemory(1024);
delete[] my_arr;
return 0;
}
- 동적 할당은 함수가 끝나도 사라지지 않음
- 종종 쓰는 디자인 패턴
주의할 점
int* getValue(int x)
{
int value = x * 2;
return &value;
}
int main()
{
int* value_1 = getValue(3);
return 0;
}
- value는 함수가 끝나면 메모리가 사라질 지역 변수
- 사라질 변수를 de-reference 하면 안 됨
- 참조 리턴도 마찬가지
int& get(std::array<int, 100>& my_arr, int ix)
{
return my_arr[ix];
}
int main()
{
std::array<int, 100> my_arr;
get(my_arr, 30) = 1024;
return 0;
}
- 위와 같이 미리 메모리를 잡고 있는 상태에서 함수로 넘기면 괜찮음
구조체 리턴
struct S
{
int a, b, c, d;
};
S getStruct() // 이거 inline 함수인가?
{
S my_s{ 1,2,3,4 };
}
int main()
{
S my_s = getStruct();
cout << my_s.b << endl;
return 0;
}
- 구조체를 이용하면 여러가지 리턴 값을 받을 수 있음
- 한 번 쓰고 마는 경우 구조체 만들기 비효율적 → 튜플 이용
튜플(tuple) 리턴
std::tuple<int, double> getTuple()
{
int a = 10;
double d = 3.14;
return std::make_tuple(a, d);
}
int main()
{
std::tuple<int, double> my_tp = getTuple();
cout << std::get<0>(my_tp) << endl; // 10 출력
cout << std::get<1>(my_tp) << endl; // 3.14 출력
return 0;
}
🚆 inline 함수
inline int min(int x, int y)
{
return (x > y) ? x : y;
}
int main()
{
cout << min(1,3) << endl;
cout << min(15,30) << endl;
return 0;
}
- 함수 앞에 inline 을 선언하면 매크로처럼 작동
inline int min(int x, int y)
{
return (x > y) ? x : y;
}
int main()
{
cout << (1 > 3) ? 1 : 3; << endl;
cout << (15 > 30) ? 15 : 30; << endl;
return 0;
}
- 다만 inline은 강제가 아닌 권유
- 예전에는 최적화를 위해 inline을 사용했다고 하는데 요즘은 컴파일러가 알아서 해준다고 함
댓글 남기기