**이동 의미론(Move Semantics)**은 C++11에서 도입된 개념으로, 객체의 리소스를 복사하지 않고 이동시켜 성능을 향상시키는 메커니즘입니다. 기존의 복사 의미론과 대비되는 개념입니다.

1. 복사 의미론 vs 이동 의미론

복사 의미론 (Copy Semantics) - C++98/03

class MyString {
    char* data;
    size_t size;

public:
    // 복사 생성자
    MyString(const MyString& other) {
        size = other.size;
        data = new char[size + 1];           // 새로운 메모리 할당
        strcpy(data, other.data);            // 데이터 복사
        std::cout << "복사 생성자 호출" << std::endl;
    }

    // 복사 대입 연산자
    MyString& operator=(const MyString& other) {
        if (this != &other) {
            delete[] data;                   // 기존 메모리 해제
            size = other.size;
            data = new char[size + 1];       // 새로운 메모리 할당
            strcpy(data, other.data);        // 데이터 복사
        }
        return *this;
    }
};

// 사용 예시 - 비효율적
MyString createString() {
    MyString temp("Hello World");
    return temp;  // 복사 발생! (RVO가 없다면)
}

MyString str = createString();  // 또 복사 발생!

이동 의미론 (Move Semantics) - C++11

class MyString {
    char* data;
    size_t size;

public:
    // 이동 생성자
    MyString(MyString&& other) noexcept {
        data = other.data;                   // 포인터만 이동
        size = other.size;

        other.data = nullptr;                // 원본을 안전한 상태로
        other.size = 0;
        std::cout << "이동 생성자 호출" << std::endl;
    }

    // 이동 대입 연산자
    MyString& operator=(MyString&& other) noexcept {
        if (this != &other) {
            delete[] data;                   // 기존 리소스 해제

            data = other.data;               // 포인터 이동
            size = other.size;

            other.data = nullptr;            // 원본 초기화
            other.size = 0;
        }
        return *this;
    }
};

2. 이동 의미론의 핵심 개념

Rvalue Reference (&&)

void func(MyString& lvalue_ref) {        // lvalue 참조
    std::cout << "lvalue 버전" << std::endl;
}

void func(MyString&& rvalue_ref) {       // rvalue 참조 (C++11)
    std::cout << "rvalue 버전 - 이동!" << std::endl;
}

MyString str("hello");
func(str);                               // lvalue 버전 호출
func(MyString("world"));                 // rvalue 버전 호출
func(std::move(str));                    // rvalue 버전 호출 (강제 이동)

이동의 조건

// 이동이 일어나는 경우들
MyString str1("Hello");
MyString str2 = std::move(str1);         // 명시적 이동
MyString str3 = createString();          // 임시 객체 이동
MyString str4 = MyString("World");       // 직접 구성, 이동

3. 이동 의미론의 장점

성능 비교

#include <chrono>
#include <vector>

class HeavyObject {
    std::vector<int> data;

public:
    HeavyObject() : data(1000000, 42) {}  // 큰 데이터

    // 복사 생성자
    HeavyObject(const HeavyObject& other) : data(other.data) {
        std::cout << "복사: 비용이 큰 작업" << std::endl;
    }

    // 이동 생성자
    HeavyObject(HeavyObject&& other) noexcept : data(std::move(other.data)) {
        std::cout << "이동: 빠른 작업" << std::endl;
    }
};

// 성능 테스트
void performance_test() {
    std::vector<HeavyObject> container;

    // 복사를 통한 추가 (느림)
    HeavyObject obj1;
    container.push_back(obj1);           // 복사 발생

    // 이동을 통한 추가 (빠름)
    HeavyObject obj2;
    container.push_back(std::move(obj2)); // 이동 발생

    // 임시 객체 추가 (자동 이동)
    container.push_back(HeavyObject());   // 자동으로 이동
}

4. 표준 라이브러리에서의 이동 의미론

std::vector와 이동

std::vector<std::string> create_vector() {
    std::vector<std::string> vec;
    vec.push_back("Hello");
    vec.push_back("World");
    return vec;  // 이동으로 반환 (또는 RVO)
}

std::vector<std::string> v1 = create_vector();  // 이동
std::vector<std::string> v2 = std::move(v1);    // 명시적 이동
// v1은 이제 빈 상태

std::unique_ptr와 이동

#include <memory>

std::unique_ptr<int> create_ptr() {
    return std::make_unique<int>(42);  // 이동으로 반환
}

auto ptr1 = create_ptr();                    // 이동
auto ptr2 = std::move(ptr1);                 // 소유권 이동
// ptr1은 이제 nullptr

5. 이동 의미론의 규칙들