TIL 2024/7/29

Sung Joo Lee·2024년 7월 29일

배열을 함수로 전달

  • 형식적 매개변수 정의에 “[ ]” 를 사용하여 배열을 전달 가능함

void print_array(int numbers []); 와 같은 방식으로 배열을 매개변수로 전달
void print_array(int* numbers);와 같다.

  • 배열의 요소들은 복사되지 않는다!
    • 배열의 이름은 배열의 첫 요소의 메모리를 가리킴
      • 실제 매개변수에 복사되는 것은 ‘배열의 첫 번째 요소의 주소값’ 이다.
  • 따라서 배열에 얼마나 많은 요소가 저장되어 있는지 함수는 알지 못함

우리가 C언어를 공부 할 때 pointer에 대한 개념을 배웠고 ‘배열의 이름’이 배열의 첫 번째 요소를 가리키는 포인터라는 것을 이미 공부했었다. “배열은 포인터다” 이에 대한 기억이 없다면 공부하고 보는 것을 추천한다.

  • 우리는 위의 개념을 이용하여 포인터를 사용하여 값에 접근이 가능하다.
void zeroArray(int numbers[], int size)
{
	for (int i = 0; i < size; i++)
	{
		numbers[i] = 0;
	}
}

위와 같은 코드를 보면 *(numbers + i)를 사용해 해당 i번째 배열에 접근해 값을 0으로 초기화 한다.

즉, 우리가 이전에 배운 pass by value와는 다르게 scope가 다른 변수에 접근해서 값의 변경이 가능하다. 이를 우리는 ‘Pass by reference’라고 배웠었다.

Pass by reference in CPP

이제 우리는 위의 개념을 ‘참조자를 사용하여 전달한다.’ 라는 의미로 받아들이면 된다.

  • Cpp에서는 ‘참조자’라는 새로운 개념을 배우게 된다.
  • 함수 내에서 값의 변환이 필요할 경우 사용
  • 배열이 아닌 경우에도 CPP에서는 참조자를 통해 가능
  • 형식 매개변수를 실제 매개변수의 별명처럼 사용하는 개념

참조자

  • & 기호를 사용
  • 포인터와는 다르게 메모리 공간을 차지하지 않는다!
    • 그럼 왜 포인터를 쓰지? 라고 생각 할 수 있는데 이는 ‘동적 할당’의 개념을 배우면 이해 할 수 있을 것이다.

void scaleNumber( int& num );

“개인적으로는 매개변수로 받는 변수에 ‘num’이라는 별명을 붙인다! “ 라고 생각하는게 편했다.

#include <iostream>

void scaleNumber(int& num);

int main()
{
	int number = 1000;
	scaleNumber(number);
	std::cout << number << std::endl;

	return 0;
}

void scaleNumber(int& num)
{
	if (num > 100)
	{
		num = 100;
	}
}

위의 코드를 한번 자세하게 봐보자

우리는 scaleNumber(number)을 보고 ‘아! number라는 변수에 num이라는 별명을 붙였구나’ 라고 생각 할 수 있다.

- 실제 그림을 그려보면 위와 같이 될 것이다.
#include <iostream>

void swap(int& a, int& b);

int main()
{
	int x = 10, y = 20;
	std::cout << x << " " << y << std::endl;
	swap(x, y);
	std::cout << x << " " << y << std::endl;

	return 0;
}

void swap(int& a, int& b) {

	int temp = a;
	a = b;
	b = temp;
}

위의 간단한 sawp 코드를 보면서 이해해 보자!

Inline 함수

  • 함수 호출에는 어느 정도 오버헤드 존재
    • stack의 할당과 제거, 매개변수 처리 , pop stack, 리턴값 처리… 등등
  • 함수를 inline으로 정의한다면 컴파일 단계에서 함수 내의 명령문으로 함수 호출이 대체
    • 이로 인해 함수 호출을 하지 않아 오버헤드 발생을 줄일 수 있다.
  • 일반적인 함수 호출보다 빠름
  • 바이너리 파일의 용량이 커질 수 있음
    • 함수를 만들어 놓고 필요 할 때 호출 하는 것이 아니라 매번 코드로 대체가 되기 때문에
  • 컴파일러에서 내부적으로 알아서 처리하기도 함
#include <iostream>

inline int addNumbers(int a, int b) {
	return a + b;
}

int main() {
	int result;
	result = addNumbers(100, 200);
	return 0;
}

요약

  • 매개변수와 pass by value (인수는 복사하여 전달된다.)
  • return문
  • 기본 인수 (default argument) (기본값 , 오른쪽부터 선언해준다.)
  • 오버로딩 ( 동일이름 , 다른 타입 , 유사 동작)
  • 배열의 전달( 요소는 복사되지 않고, 첫 요소의 주소값이 전달된다.)
  • pass by reference (함수 내에서 값 변환 ,복사 오버헤드 없음)
profile
개발로그

0개의 댓글