💡 퀵 접속: cpp.kr/move

move

C++ 표준 라이브러리의 알고리즘으로, 주어진 범위의 요소들을 다른 범위로 이동합니다. 원본 범위의 요소들은 이동 후에는 유효하지 않은 상태가 됩니다. 이동 연산은 복사보다 효율적이며, 특히 큰 객체나 리소스를 관리하는 객체를 다룰 때 유용합니다.

기본 사용법

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

int main() {
    std::vector<std::string> source = {"Hello", "World", "C++"};
    std::vector<std::string> destination(3);
    
    // source의 문자열들을 destination으로 이동
    std::move(source.begin(), source.end(), destination.begin());
    
    // 결과 출력
    std::cout << "원본 (이동 후): ";
    for (const auto& s : source) {
        std::cout << (s.empty() ? "empty" : s) << " ";
    }
    std::cout << std::endl;
    
    std::cout << "대상: ";
    for (const auto& s : destination) {
        std::cout << s << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

실행 결과:

원본 (이동 후): empty empty empty
대상: Hello World C++

사용자 정의 타입 이동

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

class Resource {
    std::string name;
    int* data;
public:
    Resource(const std::string& n, int size) : name(n), data(new int[size]) {
        std::cout << name << " 생성됨" << std::endl;
    }
    
    // 이동 생성자
    Resource(Resource&& other) noexcept : name(std::move(other.name)), data(other.data) {
        other.data = nullptr;
        std::cout << name << " 이동됨" << std::endl;
    }
    
    // 이동 대입 연산자
    Resource& operator=(Resource&& other) noexcept {
        if (this != &other) {
            delete[] data;
            name = std::move(other.name);
            data = other.data;
            other.data = nullptr;
            std::cout << name << " 이동 대입됨" << std::endl;
        }
        return *this;
    }
    
    ~Resource() {
        delete[] data;
        std::cout << name << " 소멸됨" << std::endl;
    }
};

int main() {
    std::vector<Resource> source;
    source.emplace_back("Resource1", 10);
    source.emplace_back("Resource2", 20);
    
    std::vector<Resource> destination(2);
    
    // source의 Resource 객체들을 destination으로 이동
    std::move(source.begin(), source.end(), destination.begin());
    
    return 0;
}

실행 결과:

Resource1 생성됨
Resource2 생성됨
Resource1 이동됨
Resource2 이동됨
Resource1 소멸됨
Resource2 소멸됨

컨테이너 간 이동

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <string>

int main() {
    std::list<std::string> source = {"Apple", "Banana", "Orange"};
    std::vector<std::string> destination(3);
    
    // list의 문자열들을 vector로 이동
    std::move(source.begin(), source.end(), destination.begin());
    
    // 결과 출력
    std::cout << "원본 list (이동 후): ";
    for (const auto& s : source) {
        std::cout << (s.empty() ? "empty" : s) << " ";
    }
    std::cout << std::endl;
    
    std::cout << "대상 vector: ";
    for (const auto& s : destination) {
        std::cout << s << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

실행 결과:

원본 list (이동 후): empty empty empty
대상 vector: Apple Banana Orange

참고사항

  • move는 algorithm 헤더에 정의되어 있습니다.
  • 원본 범위의 요소들은 이동 후에는 유효하지 않은 상태가 됩니다.
  • 시간 복잡도는 O(n)입니다 (n은 범위의 크기).
  • 대상 범위는 원본 범위와 크기가 같거나 더 커야 합니다.
  • 이동 연산은 복사보다 효율적이며, 특히 큰 객체나 리소스를 관리하는 객체를 다룰 때 유용합니다.
  • 이동 가능한 타입(moveable type)에 대해서만 사용할 수 있습니다.
  • 이동 후에는 원본 객체를 사용하지 않아야 합니다.
  • 리소스 관리가 필요한 객체를 다룰 때 특히 유용합니다.
함수 설명
move(first, last, result) first부터 last까지의 범위의 요소들을 result부터 시작하는 범위로 이동