icon안동민 개발노트

함수의 정의와 호출


함수의 기본 구조

 C++에서 함수의 기본 구조는 다음과 같습니다.

반환타입 함수이름(매개변수 목록) {
    // 함수 본문
    return 반환값;
}
  • 반환타입 : 함수가 작업을 마치고 반환하는 값의 데이터 타입
  • 함수이름 : 함수를 식별하는 이름
  • 매개변수 목록 : 함수에 전달되는 값들의 목록
  • 함수 본문 : 함수가 수행하는 실제 작업
  • return 문 : 함수의 결과를 호출자에게 반환

함수 정의 예시

#include <iostream>
 
int add(int a, int b) {
    return a + b;
}
 
int main() {
    int result = add(5, 3);
    std::cout << "5 + 3 = " << result << std::endl;
    return 0;
}

 이 예제에서 add 함수는 두 정수를 받아 그 합을 반환합니다.

함수 호출

 함수를 호출할 때는 함수 이름과 필요한 인자를 제공합니다.

int result = add(5, 3);  // result는 8

매개변수 전달 방식

 C++에서는 세 가지 주요 매개변수 전달 방식이 있습니다.

 값에 의한 전달 (Pass by Value)

void incrementByValue(int x) {
    x++;  // 원본 변수에 영향을 주지 않음
}
 
int main() {
    int num = 5;
    incrementByValue(num);
    std::cout << num << std::endl;  // 출력: 5
    return 0;
}

 참조에 의한 전달 (Pass by Reference)

void incrementByReference(int& x) {
    x++;  // 원본 변수를 직접 수정
}
 
int main() {
    int num = 5;
    incrementByReference(num);
    std::cout << num << std::endl;  // 출력: 6
    return 0;
}

 포인터에 의한 전달 (Pass by Pointer)

void incrementByPointer(int* x) {
    (*x)++;  // 포인터를 통해 원본 변수를 수정
}
 
int main() {
    int num = 5;
    incrementByPointer(&num);
    std::cout << num << std::endl;  // 출력: 6
    return 0;
}

반환 값

 함수는 다양한 방식으로 값을 반환할 수 있습니다.

 단일 값 반환

int square(int x) {
    return x * x;
}

 참조 반환

int& getElement(std::vector<int>& vec, int index) {
    return vec[index];
}

 void (반환 값 없음)

void printMessage(const std::string& msg) {
    std::cout << msg << std::endl;
}

함수 프로토타입

 함수 프로토타입을 사용하면 함수의 선언과 정의를 분리할 수 있습니다.

// 함수 프로토타입
int multiply(int a, int b);
 
int main() {
    std::cout << multiply(4, 5) << std::endl;  // 출력: 20
    return 0;
}
 
// 함수 정의
int multiply(int a, int b) {
    return a * b;
}

기본 매개변수

 함수의 매개변수에 기본값을 지정할 수 있습니다.

void greet(const std::string& name = "Guest") {
    std::cout << "Hello, " << name << "!" << std::endl;
}
 
int main() {
    greet();  // 출력: Hello, Guest!
    greet("Alice");  // 출력: Hello, Alice!
    return 0;
}

함수 오버로딩

 C++에서는 같은 이름의 함수를 매개변수의 타입이나 개수를 달리하여 여러 개 정의할 수 있습니다.

int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
 
int main() {
    std::cout << add(5, 3) << std::endl;     // int 버전 호출
    std::cout << add(3.14, 2.5) << std::endl;  // double 버전 호출
    return 0;
}

인라인 함수

 작은 함수를 최적화하기 위해 인라인 함수를 사용할 수 있습니다.

inline int square(int x) { return x * x; }
 
int main() {
    std::cout << square(5) << std::endl;  // 컴파일러가 최적화할 수 있음
    return 0;
}

재귀 함수

 함수가 자기 자신을 호출하는 방식을 재귀라고 합니다.

int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}
 
int main() {
    std::cout << factorial(5) << std::endl;  // 출력: 120
    return 0;
}

연습 문제

  1. 두 수를 입력받아 최대공약수(GCD)를 계산하는 함수를 작성하세요.
  2. 재귀 함수를 사용하여 피보나치 수열의 n번째 항을 계산하는 함수를 구현하세요.
  3. 함수 오버로딩을 사용하여 정수, 실수, 문자열을 인자로 받아 각각의 타입에 맞는 출력을 하는 print 함수를 작성하세요.
  4. 참조에 의한 전달을 사용하여 두 변수의 값을 교환하는 swap 함수를 구현하세요.


참고 자료

  • C++ 공식 문서의 함수 섹션 : C++ Functions
  • "Effective C++" by Scott Meyers (항목 23 : 멤버 함수보다는 비멤버 비프렌드 함수를 선호하라)
  • "C++ Primer" by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo (Chapter 6: Functions)
  • C++ Core Guidelines의 함수 관련 규칙 : F : Functions