<aside> 💡 목차


</aside>

<aside> 💡 강의 일정표


CPP 구문 심화

생성자에서 복사 & 이동대입 연산자 삭제하는 이유

<aside> 💡 [C++11] - 복사 생성자 vs 이동 생성자

[C++11] - 이동 대입 연산자 (operator=)

</aside>

<aside> 💡 Lock() 기반 스택이나 큐 작성할떄,

왜 굳이 복사생성자하고 이동대입 연산자는 왜 막은걸까?


//! lock 기반의 스택
template<typename T>
class LockStack 
{
public:
	LockStack(){};
	~LockStack(){};

	LockStack(const LockStack&) = delete; //! 복사 생성자는 삭제해버린다
	LockStack& operator=(const LockStack&) = delete; //! 대입 연산자도 삭제해버린다 
	// -> (복사하려고해도, 응 돌아가~ 하는거임)

private:
	stack<T> _stack;
	mutex _mutex;
};

</aside>

<aside> 💡 복사 생성자와 이동 대입 연산자를 막은 주된 이유는 뮤텍스가 복사되는걸 막기 위해서임

이 클래스는 내부적으로 뮤텍스(mutex)를 사용하여 스레드 안전성을 보장하고 있습니다.

뮤텍스는 복사될 수 없는 자원이며, 복사될 경우 심각한 문제를 일으킬 수 있습니다.


뮤텍스 복사 문제: 만약 LockStack 객체를 복사하게 되면, 내부의 뮤텍스도 같이 복사됩니다. 하지만 뮤텍스는 복사될 수 없는 자원입니다. 복사된 뮤텍스는 원본 뮤텍스와 독립적으로 동작하게 되어, 두 객체 간의 동기화가 깨지게 됩니다.

LockStack<int> stack1;
LockStack<int> stack2 = stack1;  // 이렇게 하면 안 됩니다!

데이터 일관성 문제: 복사나 대입이 허용된다면, 한 객체의 상태가 변경될 때 다른 객체에 반영되지 않아 데이터 일관성 문제가 발생할 수 있습니다.

LockStack<int> stack1;
stack1.push(10);
LockStack<int> stack2 = stack1;  // 복사가 허용된다고 가정
stack1.push(20);
// 이 시점에서 stack1과 stack2의 내용이 다릅니다.

소유권 문제: 복사나 대입으로 인해 여러 객체가 같은 자원을 가리키게 되면, 자원 해제 시 문제가 발생할 수 있습니다.

LockStack<int*> stack1;
stack1.push(new int(10));
LockStack<int*> stack2 = stack1;  // 복사가 허용된다고 가정
// stack1과 stack2 중 어느 것이 메모리를 해제해야 할까요?

</aside>

<aside> 💡 그림으로 보면 다음과 같다


graph TD
    A["LockStack 객체 1"]
    B["LockStack 객체 2 (복사본)"]
    C["스택 데이터"]
    D["뮤텍스"]
    E["스택 데이터 (복사됨)"]
    F["뮤텍스 (복사 시도)"]

    A -->|"포함"| C
    A -->|"포함"| D
    B -->|"포함"| E
    B -->|"복사 시도"| F

    style A fill:#0047AB,color:#FFFFFF
    style B fill:#CC5500,color:#FFFFFF
    style C fill:#006600,color:#FFFFFF
    style D fill:#551A8B,color:#FFFFFF
    style E fill:#006600,color:#FFFFFF
    style F fill:#8B0000,color:#FFFFFF

</aside>

그럼 굳이 복사 & 이동대입 연산자가 필요한 경우

<aside> 💡 게임을 예시로 들어 복사 생성자와 이동 대입 연산자의 필요성을 알아보자

graph TD
    A["게임 캐릭터"]
    B["복사된 캐릭터"]
    C["이동된 캐릭터"]
    D["인벤토리"]
    E["스킬"]
    F["장비"]

    A -->|"복사 생성자"| B
    A -->|"이동 대입 연산자"| C
    A --> D
    A --> E
    A --> F

    style A fill:#0047AB,color:#FFFFFF
    style B fill:#006600,color:#FFFFFF
    style C fill:#CC5500,color:#FFFFFF
    style D fill:#551A8B,color:#FFFFFF
    style E fill:#404040,color:#FFFFFF
    style F fill:#8B0000,color:#FFFFFF

**복사 생성자가 필요한 경우:**


class GameCharacter {
private:
    std::vector<Item> inventory;
    std::vector<Skill> skills;
    Equipment equipment;

public:
    GameCharacter(const GameCharacter& other)
        : inventory(other.inventory), skills(other.skills), equipment(other.equipment) {
        // 캐릭터의 모든 상태를 정확히 복사
    }
};

// 사용 예
GameCharacter originalChar;
GameCharacter clonedChar = originalChar;  // 복사 생성자 호출

**이동 대입 연산자가 필요한 경우:**


class GameCharacter {
public:
    GameCharacter& operator=(GameCharacter&& other) noexcept {
        if (this != &other) {
            inventory = std::move(other.inventory);
            skills = std::move(other.skills);
            equipment = std::move(other.equipment);
            other.resetCharacter();  // 원본 캐릭터 초기화
        }
        return *this;
    }

private:
    void resetCharacter() {
        // 캐릭터 상태 초기화
    }
};

// 사용 예
GameCharacter oldAccount;
GameCharacter newAccount;
newAccount = std::move(oldAccount);  // 이동 대입 연산자 호출


  1. 복사 생성자:
  2. 이동 대입 연산자: </aside>

STL 심화

TLS 는 공유영역과 개인영역 사이에 존재한다

멀티스레드는 heap과 static영역을 공유한다 🔥