반응형

1. 인라인 함수

1) ODR(One Definition Rule) 완화 → 헤더에 함수를 정의할 수 있게 함

이게 사실상 inline의 본래 의미입니다.

  • 함수 정의를 헤더 파일에 적어도 된다
  • 여러 번 포함되더라도 “복제 오류”가 나지 않도록 조절한다

즉, 링커 충돌을 막는 장치.

이 특성 덕분에 템플릿 함수는 대부분 inline 형태로 돌아다니죠.

2) 컴파일러에게 “이 함수는 인라인해도 괜찮아”라는 힌트

단, 명령이 아니라 힌트입니다.

컴파일러가 판단해서

  • 최적화 레벨
  • 함수 크기
  • 코드 중복 비용
    등을 고려한 뒤 인라인할지 말지 결정합니다.

2. 인라인 함수의 역할

함수 호출을 없애고 코드 본문을 호출 지점에 삽입해도 된다는 권한 제공

여기서 “역할”은 다음과 같아요:

  • 함수 호출 오버헤드 제거 가능
  • 작은 함수의 호출 비용을 없애 성능 개선 유도
  • 헤더 파일에 정의된 함수가 여러 번 포함될 때 링킹 오류 방지
반응형

'Programming Language > C++' 카테고리의 다른 글

Using 키워드  (0) 2025.11.06
폴드 표현식  (0) 2025.11.06
람다 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06
반응형

using 키워드

1. 상속 멤버의 접근 지정자 변경 가능(protected -> public 으로 변경할 때만 사용 가능)

#include <iostream>

using namespace std;

class character {
public:
  character() : hp(100), power(100) {};

protected:
  int hp;
  int power;
};

//character 클래스를 상속 받은 player 클래스
class player : public character {
public:
  player() {};
};

//기본 Monster 클래스
class monster {
public:
  monster() {};

protected:
  void get_damage(int _damage) {};
  void attack(player target_player) {};
  void attack_special(player target_player);
};

void monster::attack_special(player target_player) {
  cout << "기본 공격 : 데미지 - 10 hp" << endl;
}

//몬스터 A는 기본 Monster 클래스로부터 상속
class monster_a : public monster, character {
public:
  // 부모 클래스에서 protected로 선언된 get_damage 함수 접근 범위 변경
  using monster::get_damage;
private:
  //상속받은 함수 오버라이딩 
  void attack_special(player target_player);
};

void monster_a::attack_special(player target_player) {
  cout << "인텡글 공격 : 데미지 - 15 hp" << endl;
}

//몬스터 A는 기본 Monster 클래스로부터 상속
class monster_b : public monster, character {
private:
  //상속받은 함수 오버라이딩 
  void attack_special(player target_player);
};

void monster_b::attack_special(player target_player) {
  cout << "가상 공격 : 데미지 - 0 hp" << endl;
}

int main() {
  monster_a mon_1;
  monster_b mon_2;

  mon_1.get_damage(100);
  // 아래 코드는 오류가 발생합니다.
  // mon_2.get_damage(100);

  return 0;
}

2. 열거형 사용 선언(구조체 내부에 정의된 열거형처럼 사용할 수 있게 된다.)

#include <iostream>

using namespace std;

enum class weapon : int { gun, arrow, machine_gun };

class monster {
public:
  weapon weapon_type;
};

struct weapon_class {
  using enum weapon;
};

int main() {
  monster monster_obj;
  weapon_class weapon_obj;

  monster_obj.weapon_type = weapon::gun;
  monster_obj.weapon_type = weapon_obj.arrow;
  monster_obj.weapon_type = weapon_class::machine_gun;
 
  return 0;
}

3. 별칭 만들기

using MapType = std::map<int, std::string>;

template<typename T>
using Vec = std::vector<T>;
반응형

'Programming Language > C++' 카테고리의 다른 글

인라인(inline)  (0) 2025.11.10
폴드 표현식  (0) 2025.11.06
람다 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06
반응형

폴드 표현식

1. C++17 부터 도입된 폴드 표현식(fold expression)은 개수가 정해지지 않은 매개변수를 하나로 묶는 매개변수 팩을 반복해서 계산해 준다.

 

2. 사용법 (매개변수_팩_이름 연산자 ...)

예시) (show_doll(doll_list) + ...)

  • 매개변수 팩을 이용한 예시
#include <iostream>

using namespace std;

// 매개변수 팩을 이용한 가변 인자 템플릿 – 말단 함수용
template<typename doll>
// 매개변수 팩의 마지막 인자를 연산 하기 위한 함수
void find_doll(doll doll_name) {
  cout << "'" << doll_name << "'(이)가 ";
}

// 매개변수 팩을 이용한 가변 인자 템플릿 – 재귀 함수 용
template<typename doll, typename... dolls>
// find_dell 함수 오버로딩
void find_doll(doll doll_name, dolls... doll_list) {
  cout << "'" << doll_name << "' 안쪽에 ";
  // 재귀 호출
  find_doll(doll_list...);

}

int main() {
  cout << "첫 번째 마트료시카 ";
  // 가변 인자로 함수 호출
  find_doll("대형", "중형", "소형");
  cout << "있습니다." << endl << endl;

  cout << "두 번째 마트료시카 ";
  // 가변 인자로 함수 호출
  find_doll("특대형", "대형", "중형", "소형", "극소형");
  cout << "있습니다." << endl;

  return 0;
}

/*
출력 결과

첫번째 마트료시카 '대형' 안쪽에 '중형' 안쪽에 '소형' 안쪽에 있습니다.

두번째 마트료시카 '특대형' 안쪽에 '대형' 안쪽에 '중형' 안쪽에 '소형' 안쪽에 '극소형' 안쪽에 있습니다.
*/
  • 폴드 표현식 예시
#include <iostream>

using namespace std;

template<typename doll>
doll show_doll(doll doll_name) {
	return "'" + doll_name + "' 안쪽에 ";
}

template<typename... dolls>
string find_doll(dolls... doll_list) {
	// 폴드 표현식 사용
	return (show_doll(doll_list) + ...);
}

int main() {
	cout << "첫번째 마트료시카 ";
	cout << find_doll(string("대형"), string("중형"), string("소형"));
	cout << "있습니다." << endl << endl;

	cout << "두번째 마트료시카 ";
	cout << find_doll(string("특대형"), string("대형"), string("중형"), string("소형"), string("극소형"));
	cout << "있습니다." << endl;

	return 0;
}

/*
출력 결과

첫번째 마트료시카 '대형' 안쪽에 '중형' 안쪽에 '소형' 안쪽에 있습니다.

두번째 마트료시카 '특대형' 안쪽에 '대형' 안쪽에 '중형' 안쪽에 '소형' 안쪽에 '극소형' 안쪽에 있습니다.
*/
  • 실수형 데이터 연산 예시
#include <iostream>

using namespace std;

// 단항 왼쪽 폴드 표현식
template<typename... numbers>
double unary_left(numbers... num_list) {
  return (... / num_list );
}

// 단항 오른쪽 폴드 표현식
template<typename... numbers>
double unary_right(numbers... num_list) {
  return (num_list / ...);
}

// 이항 왼쪽 폴드 표현식
template<typename... numbers>
double binary_left(numbers... num_list) {
  return (10.0 / ... / num_list);
}

// 이항 오른쪽 폴드 표현식
template<typename... numbers>
double binary_right(numbers... num_list) {
  return (num_list / ... / 10.0);
}

int main() {

  cout << "단항 왼쪽 폴드 표현식: " << 
    unary_left(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) << endl;

  cout << "단항 오른쪽 폴드 표현식: " <<
    unary_right(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) << endl;

  cout << "이항 왼쪽 폴드 표현식: " <<
    binary_left(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) << endl;

  cout << "이항 오른쪽 폴드 표현식: " <<
    binary_right(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) << endl;

  return 0;
}

/*
출력 결과

단항 왼쪽 폴드 표현식: 0.00138889
단항 오른쪽 폴드 표현식: 0.3125
이항 왼쪽 폴드 표현식: 0.0138889
이항 오른쪽 폴드 표현식: 3.125
*/

 

반응형

'Programming Language > C++' 카테고리의 다른 글

인라인(inline)  (0) 2025.11.10
Using 키워드  (0) 2025.11.06
람다 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06
반응형

람다 표현식

1. 함수형 언어나 파이썬과 같은 인터프리터를 사용하는 언어에서 사용되던 클로저(Closure)가 네이티브 프로그래밍 언어에 도입되면서 람다 함수, 람다 표현식이 되었다.

 

2. 즉시 호출 형태로 사용하면 코드의 위치가 곧 호출 위치이므로 로직을 한눈에 파악할 수 있으며, 인라인(inline) 함수로 만들어 성능을 최적화하는 데도 도움이 된다.(인라인이 가능하면, 호출 오버헤드를 제거할 수 있다.)

 

3. 외부 변수 캡처 방법

  • [=] : 선언부 범위의 모든 변수 읽기 전용으로 사용 
  • [&] : 선언부 범위의 모든 변수 참조 형식으로 사용되어 읽기와 쓰기 가능
  • [변수 1] : 변수1을 읽기 전용으로 사용

4. 람다 표현식을 함수 객체로 사용하 때는 호출부를 작성하지 않는다. 또한 다른 함수나 객체에 매개변수로 전달할 경우 가급적 외부 변수를 캡처하지 않는 것이 좋다. 이유는 댕글링 포인터가 생길 수 있기 때문이다.

 

5. mutable 키워드를 이용하면 변수나 객체를 복사해서 가져올 수 있으므로, 람다 표현식 내부에서 변경된 값이 외부 변수에 영향을 주지 않는다.

예시) [&x] (int a, int b) mutable throw() -> int { return a + b; }(3, 4)

  • 람다 표현식을 즉시 실행하는 예시
#include <iostream>

using namespace std;
const int loop_count = 5;
const int change_count = 5;

class vending_machine {
public:
  vending_machine() : price{ 450, 390, 11340, 900, 150 } {};
  void stack_drink() {};

  void sale_using_basic_lambda(int payments[], int changes[]) {
    for (int i = 0; i < loop_count; ++i) {
      cout << payments[i] << "원을 내고 " << price[i] << "원 짜리 음료를 선택했습니다." << endl;
      cout << "거슬러 받을 돈은 " << [&changes](int payment, int price)->int {
        int change = payment - price;
        changes[0] = change / 1000;
        change %= 1000;
        changes[1] = change / 500;
        change %= 500;
        changes[2] = change / 100;
        change %= 100;
        changes[3] = change / 50;
        change %= 50;
        changes[4] = change / 10;
        return payment - price;
      }(payments[i], price[i]) << "입니다." << endl;
      cout << "천원 짜리 " << changes[0] << "개, 오백원 짜리 " << changes[1] << "개, 백원 짜리 " << changes[2] << "개, ";
      cout << "오십원 짜리 " << changes[3] << "개, 십원 짜리" << changes[4] << "개로 받습니다." << endl;
    }
  };

private:
  int price[loop_count];
};

int main() {
  vending_machine vending_machine_object = vending_machine();
  int payments[loop_count] = { 1000, 500, 15000, 1000, 200 };
  int changes[change_count] = { 0, };

  cout << "람다 표현식 기본 사용" << endl;
  cout << "--------------------------------------------------------------------" << endl;
  vending_machine_object.sale_using_basic_lambda(payments, changes);
  return 0;
}

/*
출력 결과

람다 표현식 기본 사용
--------------------------------------------------------------------
1000원을 내고 450원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 550입니다.
천원 짜리 0개, 오백원 짜리 1개, 백원 짜리 0개, 오십원 짜리 1개, 십원 짜리0개로 받습니다.
500원을 내고 390원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 110입니다.
천원 짜리 0개, 오백원 짜리 0개, 백원 짜리 1개, 오십원 짜리 0개, 십원 짜리1개로 받습니다.
15000원을 내고 11340원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 3660입니다.
천원 짜리 3개, 오백원 짜리 1개, 백원 짜리 1개, 오십원 짜리 1개, 십원 짜리1개로 받습니다.
1000원을 내고 900원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 100입니다.
천원 짜리 0개, 오백원 짜리 0개, 백원 짜리 1개, 오십원 짜리 0개, 십원 짜리0개로 받습니다.
200원을 내고 150원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 50입니다.
천원 짜리 0개, 오백원 짜리 0개, 백원 짜리 0개, 오십원 짜리 1개, 십원 짜리0개로 받습니다.
*/
  • 함수 객체로 사용하는 람다 표현식 예시
#include <iostream>

using namespace std;
const int loop_count = 5;
const int change_count = 5;

class vending_machine {
public:
  vending_machine() : price{ 450, 390, 11340, 900, 150 } {};
  void stack_drink() {};

  void sale_sale_using_lambda_function_object(int payments[], int changes[]) {
    auto calcu_changes = [&changes](int payment, int price)->int {
      int change = payment - price;
      changes[0] = change / 1000;
      change %= 1000;
      changes[1] = change / 500;
      change %= 500;
      changes[2] = change / 100;
      change %= 100;
      changes[3] = change / 50;
      change %= 50;
      changes[4] = change / 10;
      return payment - price;
    };

    for (int i = 0; i < loop_count; ++i) {
      cout << payments[i] << "원을 내고 " << price[i] << "원 짜리 음료를 선택했습니다." << endl;
      cout << "거슬러 받을 돈은 " << calcu_changes(payments[i], price[i]) << "입니다." << endl;
      cout << "천원 짜리 " << changes[0] << "개, 오백원 짜리 " << changes[1] << "개, 백원 짜리 " << changes[2] << "개, ";
      cout << "오십원 짜리 " << changes[3] << "개, 십원 짜리" << changes[4] << "개로 받습니다." << endl;
    }
  };

private:
  int price[loop_count];
};

int main() {
  vending_machine vending_machine_object = vending_machine();
  int payments[loop_count] = { 1000, 500, 15000, 1000, 200 };
  int changes[change_count] = { 0, };

  cout << endl << "람다 표현식 함수 객체로 사용하기" << endl;
  cout << "--------------------------------------------------------------------" << endl;
  vending_machine_object.sale_sale_using_lambda_function_object(payments, changes);
  return 0;
}

/*
출력 결과

람다 표현식 함수 객체로 사용하기
--------------------------------------------------------------------
1000원을 내고 450원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 550입니다.
천원 짜리 0개, 오백원 짜리 1개, 백원 짜리 0개, 오십원 짜리 1개, 십원 짜리0개로 받습니다.
500원을 내고 390원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 110입니다.
천원 짜리 0개, 오백원 짜리 0개, 백원 짜리 1개, 오십원 짜리 0개, 십원 짜리1개로 받습니다.
15000원을 내고 11340원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 3660입니다.
천원 짜리 3개, 오백원 짜리 1개, 백원 짜리 1개, 오십원 짜리 1개, 십원 짜리1개로 받습니다.
1000원을 내고 900원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 100입니다.
천원 짜리 0개, 오백원 짜리 0개, 백원 짜리 1개, 오십원 짜리 0개, 십원 짜리0개로 받습니다.
200원을 내고 150원 짜리 음료를 선택했습니다.
거슬러 받을 돈은 50입니다.
천원 짜리 0개, 오백원 짜리 0개, 백원 짜리 0개, 오십원 짜리 1개, 십원 짜리0개로 받습니다.
*/

 

반응형

'Programming Language > C++' 카테고리의 다른 글

Using 키워드  (0) 2025.11.06
폴드 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06
튜플과 구조적 바인딩  (0) 2025.11.06
반응형

범위 기반 for 문

1. 데이터 집합을 정확하고 안전하게 순회할 수 있다.

 

2. 순회할 수 있는 데이터 형식이 제한된다. 즉 컴파일러가 반복 횟수를 명확히 알 수 있는 데이터 형식만 사용할 수 있다.

따라서 포인터로 동적 할당한 메모리나 매개변수로 전달받은 배열은 사용할 수 없고, 반복자가 없는 stack, queue도 사용할 수 없다.

#include <iostream>
#include <array>

using namespace std;

int main(void) {
  array<int, 10> numbers { 7, 8, 2, 5, 3, 9, 0, 4, 1, 6 };

  // for 구문 활용 배열 출력
  for (int i = 0; i < 10; ++i) {
    cout << numbers[i] << " , ";
  }
  cout << endl;

  void* test = nullptr;

  // 범위 기반 for 구문 활용 배열 출력
  for ( auto &value : numbers) {
    cout << value << " , ";
  }
  cout << endl;

  return 0;
}

 

반응형

'Programming Language > C++' 카테고리의 다른 글

폴드 표현식  (0) 2025.11.06
람다 표현식  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06
튜플과 구조적 바인딩  (0) 2025.11.06
스마트 포인터  (0) 2025.11.06
반응형

L-Value

1. 메모리에 "이름" 이 있고, 그 위치가 계속 존재하는 값. 즉, 주소를 가질 수 있고, 대입문의 왼쪽에 올 수 있는 값

int x = 10; // x는 L-Value

R-Value

1. 이름이 없고, 일시적으로만 존재하는 값. 즉, 임시 값 또는 대입문의 오른쪽에만 올 수 있는 값

10      // R-value (임시 리터럴)
x + 5   // R-value (계산 결과)
func()  // R-value (함수가 반환하는 임시 값)

2. R-Value Reference 는 C++ 11에서 추가된 내용으로 이름 없는 임시 객체(R-value)를 가리킬 수 있는 참조. 즉, 기존에는 절대 참조할 수 없었던 “임시 값”을 잡아서 사용할 수 있게 해주는 기능.

 

3. 임시 객체(R-value)를 참조할 수 있게 만드는 문법이며, 이를 통해 리소스가 많이 필요한 std::string, std::vector를 복사하지 않고 특정 위치로 이동할 수 있다. move semantics와 성능 최적화

// C++ 11 이전 
void foo(int& x);   // L-value 참조
foo(10);            // ❌ 오류 (10은 임시 값 → 참조 불가)

// C++ 11 이후
void foo(int&& x);  // R-value 참조
foo(10);            // ✅ OK (10을 x로 바인딩)
#include <iostream>
#include <vector>
#include <utility>  // std::move

void takeVector(std::vector<int>&& v) {
    std::cout << "size: " << v.size() << "\n"; // size = 5
}

int main() {
    std::vector<int> big = {1, 2, 3, 4, 5};

    // big을 복사하지 않고 내부 버퍼(메모리)를 그대로 넘긴다
    takeVector(std::move(big));

    std::cout << "big size after move: " << big.size() << "\n"; // size = 0
}
반응형

'Programming Language > C++' 카테고리의 다른 글

람다 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
튜플과 구조적 바인딩  (0) 2025.11.06
스마트 포인터  (0) 2025.11.06
알고리즘  (0) 2025.11.05

+ Recent posts