C++ common sense 11

  1. std::move()
  • ref : https://modoocode.com/301

<utility> 헤더 파일에 정의되어 있다.

std::move는 어떤 객체 t가 이동 될 수 있음을 알려준다. 이동이라 함은 C++11에 도입된 개념으로 객체 t가 가지고 있는 자원을 다른 객체에게 효율적으로 전달하는 것을 의미한다.

쉽게 말해 객체 t를 rvalue reference 타입으로 static_cast 하는 것과 동일하다.

std::move된 객체를 함수에 전달한다면, rvalue reference를 인자로 받는 함수 (예를 들어 이동 생성자, 이동 대입 연산자, vector의 push_back 함수 등)가 오버로딩 되어 선택된다. 참고로 우측값 레퍼런스 자체는 rvalue가 아니라 lvalue이기 때문에, 이동 생성자나 이동 대입 연산자 내부에서 std::move를 호출하는 경우가 많다.

```cpp
// 이동 생성자
A(A &&arg) 
    : member(std::move(arg.member)) // "arg.member" 식 자체는 좌측값(lvalue) 이다.
{}

// 이동 대입 연산자
A& operator=(A&& other) {
    member = std::move(other.member);
    return *this;
}
``` 한 가지 주의할 점은 이미 이동되서 껍데이만 남은 객체를 접근하면 안 된다.
  std::vector<std::string> v;
  std::string str = "example";
  v.push_back(std::move(str));  // str은 이제 껍데기만 남았다.
  str.back();  // 정의되지 않은 작업!
  str.clear();  // 다만 clear 자체는 가능하다.

실행 예제는 다음과 같다.

  #include<iostream>
  #include<string>
  #include<utility>
  #include<vector>

  int main() {
    std::string str = "hello";
    std::vector<std::string> v;

    // push_back(const T&)가 오버로딩되어서 문자열의 복사가 발생한다.
    v.push_back(str);
    std::cout << "After copy, str is \"" << str << "\"n";
    
    // push_back(cont T&&)가 오버로딩되어서 문자열 복사 없이 그대로 전달된다. 
    v.push_back(std::movd(str));

    // 일반적으로 이동된 객체를 접근하는 것은 안되지만 C++ string의 경우 비어있음이 보장된다.
    std::cout << "After copy, str is \"" << str << "\"n";
    
    std::cout << "The contents of the vector are \"" << v[0] << "\", \"" << v[1] << "\"\n";
    // The contents of the vectors are "hello", "hello"
  }