Unreal 개발 본 캠프 12일차

HappyCircle·2025년 12월 12일

Unreal 개발

목록 보기
29/163

오늘 학습 진행 내용
라이브 세션
알고리즘 강의2

포인터 및 참조자에 대하여
메모리는 컴퓨터가 프로그램을 실행하는 동안 데이터를 저장하는 커다란 보관함

  • 메모리 주소
    실제 컴퓨터 메모리에 있는 아주 많은 연속된 작은 저장칸에 기본적인 단위정보(1바이트)를 담고 이 칸 하나하나가 고유한 주소를 가짐
  • 연속적인 공간 & 주소의 효용성
    실제 메모리 내부는 끝없이 이어진 많은 칸들이 나열(연속된 하나의 큰 공간)
    메모리 칸들도 0x1000, 0x1001,0x1002 처럼 번호가 하나씩 증가, 해당 주소 덕분에 수많은 메모리 칸들 중에서 특정 칸 정확히 찾아 갈 수 있음

변수를 선언 단계
1. 메모리 어딘가에 val 이라는 변수를 위한 공간 확보
2.해당 공간에 우리가 저장하고 싶은 데이터 저장
3.우리가 붙인 변수 이름으로 해당 메모리 공간 간접 참조

포인터는 메모리의 주소를 저장하는 특별한 타입의 변수

		int val = 7;
		int* p_val = &val;

int* 는 정수형 데이터를 가리키는 포인터 선언
&val는 변수 val의 주소를 가져옴
p_val이란 포인터에 val 값이 실제로 저장된 메모리 주소 저장

포인터 변수는 연산자를 통해 간접 참조
p_val 은 저장된 메모리 주소의 실제 값 불러옴

포인터 자체의 크기는 시스템 아키텍처에 따라 달라짐
32비트 -> 4바이트, 64비트 ->8바이트가 일반적임
가리키는 대상의 타입과 상관 없이 포인터는 메모리 주소 하나를 저장하는 공간이어서
단 포인터 자체 크기와 별개로 산술 연살을 할 때 타입을 일치시키지 않으면 버그 발생.
포인터 산술 연산은 포인터 가리키는 타입의 크기에 따라 이동단위 달라져서 잘못된 형변환은 메모리 참조 오류 발생

	int arr_size;
	cin>> arr_size;
	int arr[arr_size]; // 해당 코드 에러 발생

일반 배열은 스택 영역에 할당되고 스택 영역은 컴파일 시점에 크기가 결정되는 메모리 영역
실행 시간에 입력 받은 크기는 스택에 메모리 할당하는 것이 c++ 상에서는 불가능.
C++은 컴파일 시점에 모든 변수의 크기와 위치가 결정(중요 사항)

	int arr_size;
	cin>> arr_size;
	int* arr = new int[arr_size];

배열의 크기 동적으로 할당하고자 원할 때는 포인터 타입으로 배열 동적 할당 가능, 동적 할당(new)를 통해 메모리 관리 가능
메모리를 효율적으로 사용하는데 포인터는 필수적

이렇게 할당/해제에 대한 리스크(메모리 누수)를 우려하여 스마트 포인터 개념 등장

포인터와 배열의 관계
포인터와 배열은 밀접한 관련성 존재, 배열 이름 자체가 포인터처럼 동작
배열 이름 = 배열의 첫번째 원소의 주소를 가리키는 상수 포인터(배열 선언되면 변경 불가)
arr = &arr[0] 과 동일

원시 배열은 포인터로 전달할 때 배열 크기를 별도로 전달하는게 매우 중요

	// 배열을 함수의 매개변수로 받을 때, 배열 이름은 포인터로 전달되므로
	// 보통 이렇게 포인터 변수 타입으로 매개변수 형식을 정의합니다!
	void modify_array(int* arr, int size) {
    		for (int i = 0; i < size; i++) {
       	 		arr[i] += 10; // 아 보기 편하다! 배열 표기법! 
                      			// arr[i]는 내부적으로 *(arr+ i)로 치환이 되니 이렇게 쓰세요!
    		}
	}

해당 불편한 점 때문에 STL의 array, vector를 많이 사용(이것들은 배열의 크기 정보를 내부적으로 관리)

동적 배열 예시(포인터 배열)

		void print_dynamic_array(int* ptr, int size) {
			for (int i = 0; i < size; i++) {
				cout << ptr[i] << " ";
			}
			cout << endl;
		}

		int main() {
			int* ptr = new int[5]; // 동적 배열
			for (int i = 0; i < 5; i++) {
				ptr[i] = (i + 1) * 10;
			}

			print_dynamic_array(ptr, 5); // 정적 배열과 다를게 없이 똑같이 변수 이름을 넘겨줘요.

			delete[] ptr; // 한번 더! 동적 배열은 다 썼으면 반드시 해제는 필수!
		}

정적 배열과 동적 배열 비교
정적 배열 : 스택 메모리, 컴파일 시점 크기 결정, 자동 해제
동적 배열 : 힙 메모리, 런타임 크기 결정, 수동 해제

포인터 요약

  • 배열 이름은 포인터처럼 동작하지만 진짜 포인터는 아님(배열 이름은 상수 포인터로 첫번째 원소 가리킴)
  • 포인터 산술 연산은 포인터 타입에 따라 이동단위 달라지므로 주의
  • 배열을 함수로 전달하면 배열이 아니라 포인터로 전달
  • 배열 크기가 필요하면 별도로 전달
  • 동적 메모리 할당 시 delete[]를 반드시 사용해 메모리 해제(실수 방지를 위해 vector 사용)

참조자
기존 변수 혹은 객체에 대한 별칭을 제공하는 개념(기존 변수 혹은 객체와 같은 메모리 공간을 공유)

참조자와 포인터의 차이
참조자는 선언과 동시에 무언가를 참조해야 됨(초기화는 무조건 필수)
포인터는 nullptr이 될수 있지만 참조자는 그런 개념 존재 X(참조자는 항상 유효한 대상을 가리킴)
포인터가 *p_val 처럼 값에 접근하는 것과 달리 참조자는 별도 표기 없이 바로 그 값

원본 값을 변경하고 싶다면 참조자나 포인터를 명시적으로 사용
포인터는 간접 참조 문법 써줘야되서 귀찮거나 가독성 떨어짐
함수 매게 변수 참조자의 형태가 많이 활용

참조자에 대한 정리

  • 참조자는 별칭을 제공하는 문법, 가독성과 편의성 향상 시키는데 유용
  • 선언 시 반드시 유효한 대상 초기화, 한번 참조 대상을 정하면 변경 불가
    -함수 매개변수에 참조자 사용하는 패턴 많고, 큰 객체르 매개변수로 넘길 때 복사 발생하지 않아 성능 면에서 유리

동적 메모리 관리 혹은 재할당 해야되는게 아니면 참조자 고려
동적 메모리 할당할 때는 포인터 타입의 변수를 많이 사용
동적 메모리 할당하는 경우는 컴파일 시점에 크기를 알수 없는 경우 또는 객체의 생존 주기를 명시적으로 관리해야 하는 경우


게임 개발자를 위한 C++ 문법
챕터2-2. 템플릿
함수 오버로딩
C언어와 딜리 특정 규칙만 지키면, C++에서는 동일한 이름의 함수를 여러 개 정의 가능
C++은 함수 이름과 매개변수 타입 정보를 함께 사용해서 구분지음.
함수의 이름 구분을 위해 내부적으로 고유한 이름을 부여하는 것을 네임 맹글링(Name Mangling)이라고 함.
단, 함수의 반환형만으로는 오버로딩 성립 X

  • 함수 오버로딩 유효 조건
    • 매개 변수 타입이 다른 경우
    • 매개변수의 개수가 다른 경우
  • 함수 오버로딩이 유효하지 않은 조건
    • 타입 변환이 가능한 매개변수로 인해 두 개 이상의 오버로딩된 함수가 호출후보가 된 경우
    • 디폴트 매개 변수로 인해 함수 호출 형태가 중복되는 경우
    • 매개변수의 타입만 포인터와 배열로 다른 경우
    • 함수의 반환 타입만 다른 경우
  • 함수 오버로딩의 순서
    C++에서는 해당 우선순위 규칙에 따라 호출할 함수를 결정
  1. 정확한 매칭
    호출인자 타입과 매개 변수타입이 정확히 일치하는 경우
  2. 타입 승격 변환
    값이 손실 되지 않는 방향으로 변환하는 것을 승격
  • char 또는 short -> int
  • float -> double
  • bool -> int
  1. 표준 타입 변환
    승격 보다 조금 더 광범위, 값 손실이 발생하는 경우 존재
  • int -> double
  • double -> int
  • double -> float
  1. 사용자 정의 타입 변환
    클래스 타입의 변환 함수나 생성자 등을 통해 이뤄지는 변환

함수 오버로딩 예시 코드

#include <iostream>
using namespace std;

//목적 : 함수 오버로딩의 개념을 매개변수 타입이 다른 경우로 이해하기
//정확한 매개변수 타입이 우선적으로 선택됨(int형은 두 print 호출은 가능하지만 int형 타입 정확히 일치하는 정수 출력 print가 호출됨.)
//정확한 타입이 없으면 타입 승격 변환(작은 범위의 자료형이 큰 범위의 자료형으로 변환)이 우선적으로 선택됨
//double 값을 오버로딩된 int 또는 string 함수에 전달할 때, 변환 우선순위 확인
void print(int a){
    cout<<"정수 출력: " << a << endl;
}

void print(double a){
    cout<< "실수 출력: " << a << endl; 
}
void print(char a){
    cout<<"char 타입 호출됨" << endl;
}

void print(string a){
    cout<< "string 버전 호출됨"<<endl;
}

// void print(long a) {
//     cout << "long: " << a << endl;
// }

//double과 long 타입의 경우 int 형이 올 경우 모두 변환 가능해서 print(double), print(long) 이런식으로 정의하면 컴파일 에러 발생

//목적 : 표준 변환이 불가능하면 사용한 정의 변환이 호출됨
class MyNumber {
    public:
        operator int() const {return 42;}
};

//목적 : 매개변수의 개수가 달라서 함수 오버로딩이 유효한 경우를 확인하기
int add(int a, int b){
    return a+b;
}

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

//목적 : 디폴트 매개변수로 인해 호출 형태가 중복 되는 경우
// void display(int a, int b=5){
//     cout<<a<<", "<<b<<endl;
// }

// void display(int a){
//     cout<< a<< endl;
// }

//display(10); //디폴트 매개 변수 로 인해 두 display 함수 모두 호출 가능해서 컴파일 에러 발생

//목적 : 매개변수의 타입이 포인터와 배열 일 때 애매모호성 발생
// void print(int* arr){
//     cout<<"포인터 호출됨"<<endl;
// }
// void print(int arr[]){
//     cout<<"배열 호출됨"<<endl;
// }

// int data[3] = {1,2,3};
// print(data); //포인터와 배열(포인터가 배열의 첫 원소의 주소 가리킴)은 같은 타입으로 취급되어 둘다 호출이 가능해서 컴파일 에러 발생(배열, 포인터 매개변수로 구분 X)

//목적 : 반환 타입만 다른 함수 오버로딩으로 애매모호성 발생
// int getValue(){
//     return 10;
// }
// int getValue(){
//     return 3.14;
// }
// cout<<getValue(); //반환 타입만으로 함수 구별할 수 없으므로 컴파일 에러 발생



int main(){
    print(10);
    print(3.14);
    short s = 10; // short에서 int로 승격 변환
    print(s);

    double num = 10.99;

    print(num); // double → int 변환이 발생하여 int 버전 호출

    MyNumber mynum;
    print(mynum);  // 사용자 정의 변환을 통해 MyNumber→int로 변환됨

    cout<<add(1,2)<<endl; //두 개의 인자 사용
    cout<<add(1,2,3)<<endl; //세 개의 인자 사용

    return 0;
}

템플릿
템플릿은 타입에 관계없이 일반화된 코드를 작성하기 위한 문법
템플릿을 이용한 일반화된 함수는 아래와 같은 형태로 정의

	template <tymename T>

어떤 타입이 올지 모르더라도 그 타입을 T로 부른다는 의미

템플릿 사용 예시 코드

#include <iostream>
#include <string>
using namespace std;

//목적 : 함수 템플릿을 이용해 두 값을 더하는 일반화된 함수 작성하기
template <typename T>
T add(T a, T b){
    return a+b;
}

//목적 : 함수 템플릿을 이용하여 일반화된 최대값 찾기
template <typename T>
T getMax(T a, T b){
    return (a>b) ? a:b;
}

//목적: 함수 템플릿으로 배열 원소 출력 일반화하기
template <typename T>
void printArray(T arr[], int size){
    for (int i=0; i< size; i++){
        cout<< arr[i]<< " ";
    }
    cout<< endl;
}

template <typename T>
void swapValue(T &a, T &b){
    T temp = a;
    a = b;
    b = temp;
}

//목적 : 두 값이 같은지 확인하는 함수를 템플릿으로 구현
template <typename T>
bool isEqual(T a, T b){
    return a == b;
}

int main() {
    cout << add(3,5)<<endl;
    cout<< add(2.5,4.1)<<endl;

    cout<<getMax(10,20)<<endl;
    cout<<getMax(3.5,2.7)<<endl;
    cout<<getMax(string("apple"),string("banana"))<<endl;

    int intArr[3] = {1,2,3};
    char charArr[4] = {'A','B','C','D'};

    printArray(intArr,3);
    printArray(charArr,4);

    int x=10, y=20;
    swapValue(x,y);
    cout<<"Swapped int value: x = " << x << ", y = " << y << endl;

    double p = 3.14, q = 2.71;
    swapValue(p,q);
    cout<<"Swapped double values: p = "<< p << ", q = " << q<< endl;

    cout<< boolalpha;//C++에서 bool 값을 문자 그대로 true/false로 출력하도록 설정
    cout<< "Are 10 and 10 equal? " << isEqual(10,10) << endl;
    cout<< "Are 3.5 and 2.7 equal? " << isEqual(3.5,2.7)<< endl;
    cout<< "Are 'a' and 'b' equal? " << isEqual('a','b')<< endl;

    return 0;
}

템플릿 클래스
함수뿐만 아니라, 클래스도 템플릿으로 사용해 일반화
배열에 원소를 추가하고 삭제하는 기능을 가진 클래스를 정의할 때도 템플릿을 활용하여 다양한 타입의 데이터에 대해 동작하도록 일반화

Array 클래스 예시에 대한 요구 사항

  • 내부에 최대 100개 원소를 저장할 수 있는 배열과, 원소 개수를 나타내는 변수를 갖음
  • 생성자에서 초기 원소 개수는 0으로 함
  • add() 메서드를 구현, 인자를 받고 원소를 배열 맨 끝에 추가, 100개를 초과하면 더 이상 원소 받지 않음
  • remove() 메서드를 구현, 현재 저장된 원소가 1개 이상이면 미자막 원소 제거
  • print() 메서드 구현, 현재 저장된 모든 원소를 출력

Array 클래스 예시 코드

#include <iostream>            // 입출력을 위해 iostream 라이브러리 포함
using namespace std;           // std:: 없이 cout, endl 등을 사용하기 위해

// 목적 : 클래스 템플릿으로 배열을 일반화하여 원소 추가 및 삭제 기능 구현하기
template <typename T>          // 템플릿 선언: 어떤 자료형 T든 사용할 수 있게 함
class Array {
    T data[100];               // T 타입의 고정 크기 배열(최대 100개 저장 가능)
    int size;                  // 현재 저장된 원소 개수
public:
    Array() : size(0) {}       // 생성자: 초기 size를 0으로 설정

    void add(const T& element) {   // 배열에 요소를 추가하는 함수
        if(size < 100)             // 배열이 가득 차지 않았는지 확인
            data[size++] = element; // 요소 저장 후 size 증가
    }

    void remove() {                // 마지막 요소를 제거하는 함수
        if(size > 0)               // 배열이 비어있지 않은 경우에만
            size--;                // size만 줄이면 마지막 원소는 덮어써지므로 자동 제거
    }

    void print() {                 // 배열의 모든 원소 출력
        for(int i = 0; i < size; i++) {
            cout << data[i] << " "; // 각 원소 출력
        }
        cout << endl;              // 줄바꿈
    }
};

int main() {
    Array<int> arr;          // int 타입을 저장하는 Array 객체 생성
    arr.add(10);             // 배열에 10 추가
    arr.add(20);             // 배열에 20 추가
    arr.add(30);             // 배열에 30 추가
    arr.print();             // 현재 배열 출력 → 10 20 30

    arr.remove();            // 마지막 원소(30) 제거
    arr.print();             // 출력 → 10 20

    return 0;                // 프로그램 종료
}

템플릿 실습 코드
오버로딩 된 함수 템플릿으로 변경하기
오버로딩된 함수를 템플릿으로 변경해 봅시다.

우리는 타입이 동일한 두 개의 인자를 받고 이를 더해서 반환하는 템플릿 함수를 구현해야 합니다.

기존에 제공된 오버로딩 된 함수를 분석해서 하나의 템플릿 함수로 구현하시면 됩니다.

#include <iostream>

using namespace std;

//아래 3개의 함수를 하나의 템플릿 함수로 통합하세요
int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

std::string add(const std::string& a, const std::string& b) {
    return a + b;
}


//아래 테스트 코드는 변역하지 마세요
int main() {
    // 정수 더하기
    cout << "3 + 5 = " << add(3, 5) << endl;

    // 실수 더하기
    cout << "2.5 + 4.3 = " << add(2.5, 4.3) << endl;

    // 문자열 합치기
    cout << "\"Hello, \" + \"World!\" = " << add(string("Hello, "), string("World!")) << endl;

    // 아래 코드는 컴파일 에러가 발생해야 함
    // cout << add(true, false) << endl;

    return 0;
}

실습 코드

#include <iostream>

using namespace std;

template<typename T>
T add(T a, T b){
    return a+b;
}

//아래 테스트 코드는 변역하지 마세요
int main() {
    // 정수 더하기
    cout << "3 + 5 = " << add(3, 5) << endl;

    // 실수 더하기
    cout << "2.5 + 4.3 = " << add(2.5, 4.3) << endl;

    // 문자열 합치기
    cout << "\"Hello, \" + \"World!\" = " << add(string("Hello, "), string("World!")) << endl;

    // 아래 코드는 컴파일 에러가 발생해야 함
    // cout << add(true, false) << endl;

    return 0;
}

챕터2-3: STL 기초 -1
STL(Standard Template Library)는 C++의 표준 라이브러리의 일부로, 컨테이너, 알고리즘, 반복자 등의 템플릿 기반 구성 요소를 포함
STL을 활용하면 다양한 자료구조와 알고리즘을 직접 구현하지 않고도 사용 가능

컨테이너
컨테이너는 데이터를 담는 자료구조
데이터를 담는 방식이나 제공하는 메서드에 따라 여러가지 컨테이너 제공

  • 모든 컨테이너는 템플릿으로 구현, 다양한 타입의 데이터 저장 가능
  • 모든 컨테이너는 메모리 관리를 내부적으로 함, 사용 시 메모리 해제 직접 고려하지 않아도 됨
  • 대부분 컨테이너는 반복자를 제공, 따라서 내부 구현 몰라도 동일한 방식으로 컨테이너 순회 가능

벡터
벡터는 배열과 매우 유사한 컨테이너
벡터의 대표적인 특징

  • 템플릿 클래스로 구현되어 특정 타입에 종속되지 않음
  • 삽입되는 원소 개수에 따라 내부 배열의 크기가 자동으로 조정
  • 임의 접근이 가능(인덱스를 통해 특정 위치에 접근)
  • 삽입/삭제는 맨뒤에 하는 게 좋음(중간 삽입/삭제는 배열 복사가 필요 비효울)

벡터의 동작

  • push_back : 백터의 맨 끝에 원소를 추가하는 메서드(원소 개수 늘어남에 따라 크기 자동 증가)
  • pop_back : 벡터의 맨 끝에 원소를 제거하는 메서드(맨 끝 원소가 제거되면 벡터 크기가 자동으로 줄어듬)
  • size : 현재 벡터의 크기(원소의 개수)를 확인하는 메서드
  • erase : 특정 위치의 원소를 제거하는 메서드(중간 원소 삭제할 때 많은 원소 옮겨야 해서 시간 복잡도 커짐)

벡터의 사용 예시 코드

#include <vector>
#include <iostream>

using namespace std;

int main() {
    //벡터 기본생성 & 특정 값으로 초기화
    vector<int> vec1;

    //특정 크기와 초기값으로 벡터 선언
    vector<int> vec2(5,10); // 크기 5, 모든 원소가 10으로 초기화

    //리스트 초기화로 벡터 선언
    vector<int> vec3 = {1,2,3,4,5};

    //기존 벡터를 복사해서 벡터 선언
    vector<int> vec4(vec3);
    //vector<int> vec4 = vec3;

    //2차원 벡터 초기화
    vector<vector<int>> vec2D(3,vector<int>(4,7));

    //벡터의 끝에 원소를 추가하는 예시
    vector<int> vec;
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);

    cout << "Vector after push_back: ";
    for (int num : vec) {
        cout << num << " ";
    }

    //벡터의 마지막 원소를 제거하는 예시
    vec.pop_back();
    cout<<"Vector after pop_back: ";
    for(int num : vec){
        cout<<num<<" ";
    }

    //벡터의 현재 크기를 확인하는 예시
    cout << "Size of vector: " << vec.size() << endl;

    //벡터의 특정 위치 원소를 삭제하는 예시
    vector<int> vec_er = {10,20,30,40,50};
    vec.erase(vec.begin()+1);// 두 번째 요소 제거(index 1)

    vec.erase(vec.begin()+1, vec.begin()+3); //2~4 번째 요소 제거 (index 1~3)

    return 0;
}


맵은 키를 활용하여 값과 쌍으로 저장 검색
맵의 주요한 특성

  • 키-값 쌍은 pair(const Key, Value>
  • 키값을 기준으로 내부 데이터가 자동으로 정렬
  • 중복된 키값을 허용하지 않음

맵의 선언
맵을 선언할 때는 키-값 저장하기 위해 키 타입과 값 타입 두가지 지정, 두 타입은 동일 혹은 달라도 됨
키 타입은 비교 연산이 가능

맵의 동작

  • map은 key 순으로 오름차순 정렬, 삽입 및 삭제 발생 시 내부적으로 정렬 상태 유지

  • insert() 메서드 사용이 가능
    make_pair()를 이용하여 pair() 객체 혹은 {}로
    insert 함수 사용 가능
    [key]를 사용해서 값 추가도 가능

  • find() 메서드를 사용하면 특정 키가 map에 존재하 는지 확인 가능
    find는 키가 존재하면 해당 키의 이터레이터 반환, 존재하지 않으면 map.end()를 반환

  • size()는 맵에 키-값 쌍의 갯수를 반환하는 함수

  • erase(key) 메서드는 맵의 특정 key를 가진 요소만 삭제

  • clear() 메서드는 맵에 있는 모든 원소를 삭제하는 함수, 추가적으로 대부분의 컨테이너에 존재하는 기능

    맵의 사용 예시 코드

#include <map>
#include <iostream>

using namespace std;
int main(){
    //기본적인 map 선언 및 사용(키와 값이 다름)
    map<int,string> studentMap; //정수 키와 문자열 값을 저장하는 map
    studentMap[101] = "Alice"; //요소 추가
    studentMap[102] = "Bob"; // 요소 추가
    for (const auto& pair : studentMap){ //요소 출력(pair로 불러와서 first, seoncd로 key, value 불러옴)
        cout<<"ID: " << pair.first << ", Name: "<<pair.second<<endl;
    }

    //기본적인 map 선언 및 사용(키와 값이 같음)
    map<string, string> countryMap; //문자열 키와 문자열 값을 저장하는 map
    countryMap["KR"] = "Korea";     // 요소 추가
    countryMap["US"] = "United States";     // 요소 추가

    //키 순으로 데이터가 출력되는 것을 보여주는 예시
    map<int, string> myMap;
    myMap[20] = "Banana"; //정렬되지 않은 순서로 요소 추가
    myMap[5] = "Apple";  //정렬되지 않은 순서로 요소 추가
    myMap[15] = "Cherry";  //정렬되지 않은 순서로 요소 추가
    myMap[10] = "Grapes";  //정렬되지 않은 순서로 요소 추가
    for(const auto& pair : myMap){
        cout<<"Key : "<<pair.first << ", Value : "<<pair.second<<endl;
    }

    //insert()와 make_pair 사용한 추가
    map<int, string> insertMap;
    insertMap.insert(make_pair(1, "Apple"));  //make_pair()를 사용하여 insert()
    insertMap.insert(make_pair(2, "Banana"));  //make_pair()를 사용하여 inser()
    insertMap.insert(make_pair(3, "Cherry"));  //make_pair()를 사용하여 inser()

    //insert()와 {} 사용한 추가
    insertMap.insert({4, "Dog"});
    insertMap.insert({5,"Elephant"});
    insertMap.insert({6,"Frog"});

    //[] 연산자로 값 추가
    insertMap[7] = "Giraffe";
    insertMap[8] = "Horse";
    insertMap[9] = "Iguana";

    //find()로 특정 키 찾기
    int key= 2;
    auto it = insertMap.find(key);
    if (it != insertMap.end()) { //it key의 위치(이터레이터로 포인터와 비슷한 기능)이 end()가 아니면 insertMap 내에 존재한다는 의미
        cout << "Found! Key: " << it->first << ", Value: " << it->second << endl;
    } else {
        cout << "Key " << key << " not found!" << endl;
    }

    //기본적인 size 사용
    cout << "Map size: " << insertMap.size() << endl;

    //특정 key를 가진 요소 삭제
    cout << "Before erase, size: " << insertMap.size() << endl;
    insertMap.erase(2); // 특정 키 삭제
    cout << "After erase(2), size: " << insertMap.size() << endl;

    //존재하지 않는 key를  삭제할 경우  
    int removed = insertMap.erase(40);  // 존재하지 않는 키 삭제 시도
    if (removed == 0) {
        cout << "Key 40 not found. No deletion performed." << endl;
    }

    //clear를 통해 맵의 모든 원소를 삭제하는 예시
    cout << "Before clear, size: " << myMap.size() << endl;
    myMap.clear();  // 모든 요소 삭제
    cout << "After clear, size: " << myMap.size() << endl;
    return 0;
}
profile
개발합시다!

0개의 댓글