<utility> 에 정의됨
// C++ 14 이전에는 constexpr 아님!
template <class T>
constexpr typename std::remove_reference<T>::type&& move(T&& t) noexcept;
std::move 는 어떤 객체 t 가 이동 될 수 있음 을 알려준다. 이동 이라 하면 C++ 11 에 도입된 개념으로 t 가 가지고 있는 자원을 다른 객체에게 효율적으로 전달하는 것을 의미한다.
std::move 된 객체를 함수에 전달한다면, 우측값 레퍼런스를 인자로 받는 함수(예를 들어서 이동 생성자, 이동 대입 연산자, vector 의 push_back 함수 같은 애들)가 오버로딩 되어서 선택된다. 참고로 우측값 레퍼런스 자체는 rvalue 가 아니라 lvalue 이기 때문에, 이동 생성자나 이동 대입 연산자 내부에서 std::move 를 호출하는 경우가 많다. (아래 예시 참조)
// 이동 생성자
A(A&& arg)
: member(
std::move(arg.member)) // "arg.member" 식 자체는 좌측값 (lvalue) 이다.
{}
// 이동 대입 연산자
A& operator=(A&& other) {
member = std::move(other.member);
return *this;
}
유일한 예외적인 상황은 함수 인자가 템플릿 인자의 우측값 레퍼런스인 경우 이다 (이를 보통 Universal reference 라고 한다). 이 경우 std::forward 를 사용해야 한다.
한 가지 주의할 점으로 이미 이동되서 껍데기만 남은 객체를 접근하면 안된다. 예를 들어서
std::vector<std::string> v;
std::string str = "example";
v.push_back(std::move(str)); // str 은 이제 껍데기만 남음
str.back(); // 정의되지 않은 작업!
str.clear(); // 다만 clear 자체는 가능하다.
// 반환값, 여기서 t는 이동시키고자 하는 객체
static_cast<typename std::remove_reference<T>::type&&>(t);
#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(T&&) 가 오버로딩 되서 문자열의 복사 없이 그대로 전달된다.
v.push_back(std::move(str));
// 일반적으로 이동된 객체를 접근하는 것은 안되지만 C++ string 의 경우
// 비어있음이 보장된다.
std::cout << "After move, str is \"" << str << "\"\n";
std::cout << "The contents of the vector are \"" << v[0] << "\", \"" << v[1]
<< "\"\n";
}
After copy, str is "Hello"
After move, str is ""
The contents of the vector are "Hello", "Hello"
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 함수 객체 (Functor) / () 연산자 오버로딩 (0) | 2022.11.08 |
---|---|
C++ 클래스 접근제한자 관련 보충 내용 (0) | 2022.11.07 |
C++ 해시(Hash)의 의미 그리고 구현 (0) | 2022.10.31 |
C++ 변수와 함수에서의 const (0) | 2022.10.28 |
C++ 난수 생성 std::random + 생성 시간 측정하는 std::chrono 라이브러리 (0) | 2022.10.24 |