std:: move
|
헤더 파일에 정의됨
<utility>
|
||
|
template
<
class
T
>
typename std:: remove_reference < T > :: type && move ( T && t ) noexcept ; |
(C++11부터)
(C++14 이전까지) |
|
|
template
<
class
T
>
constexpr std:: remove_reference_t < T > && move ( T && t ) noexcept ; |
(C++14부터) | |
std::move
는 객체
t
가 "이동될 수 있음"을
나타내기 위해
사용되며, 즉
t
에서 다른 객체로 자원의 효율적인 전송을 허용합니다.
특히,
std::move
는 인자
t
를 식별하는
xvalue 표현식
을 생성합니다. 이는 rvalue 참조 타입으로의
static_cast
와 정확히 동일합니다.
목차 |
매개변수
| t | - | 이동될 객체 |
반환값
static_cast < typename std:: remove_reference < T > :: type && > ( t )
참고 사항
rvalue 참조 매개변수를 받는 함수들(
이동 생성자
,
이동 할당 연산자
, 그리고
std::vector::push_back
과 같은 일반 멤버 함수들)은
오버로드 해결
을 통해
rvalue
인수들(임시 객체와 같은
prvalue
들이나
std::move
에 의해 생성된 것과 같은
xvalue
)로 호출될 때 선택됩니다. 인수가 리소스를 소유하는 객체를 식별하는 경우, 이러한 오버로드들은 인수가 보유한 리소스들을
이동
할 수 있는 선택권을 가지지만, 그렇게 할 의무는 없습니다. 예를 들어, 연결 리스트의 이동 생성자는 리스트의 헤드에 대한 포인터를 복사하고 개별 노드들을 할당하고 복사하는 대신 인수에
nullptr
를 저장할 수 있습니다.
rvalue reference
변수의 이름은
lvalues
이며, rvalue reference 매개변수를 받는 함수 오버로드에 바인딩되려면
xvalues
로 변환되어야 합니다. 이것이 바로
move constructors
와
move assignment operators
가 일반적으로
std::move
를 사용하는 이유입니다:
// 단순 이동 생성자 A(A&& arg) : member(std::move(arg.member)) // "arg.member" 표현식은 좌측값입니다 {} // 단순 이동 할당 연산자 A& operator=(A&& other) { member = std::move(other.member); return *this; }
한 가지 예외는 함수 매개변수의 타입이 forwarding reference (타입 템플릿 매개변수에 대한 rvalue reference처럼 보이는)인 경우로, 이때는 std::forward 가 대신 사용됩니다.
명시적으로 지정되지 않는 한, 이동된 모든 표준 라이브러리 객체는 "유효하지만 지정되지 않은 상태"에 놓이게 되며, 이는 객체의 클래스 불변 조건이 유지됨을 의미합니다(따라서 이동된 후에도 사전 조건이 없는 함수들, 예를 들어 할당 연산자 등을 객체에 대해 안전하게 사용할 수 있습니다):
std::vector<std::string> v; std::string str = "example"; v.push_back(std::move(str)); // str은 이제 유효하지만 지정되지 않은 상태입니다 str.back(); // size() == 0일 경우 정의되지 않은 동작: back()에는 !empty() 선행 조건이 있습니다 if (!str.empty()) str.back(); // OK, empty()에는 선행 조건이 없으며 back() 선행 조건이 충족됩니다 str.clear(); // OK, clear()에는 선행 조건이 없습니다
또한, xvalue 인수를 사용하여 호출된 표준 라이브러리 함수는 해당 인수가 객체에 대한 유일한 참조라고 가정할 수 있습니다; 만약 lvalue에서
std::move
로 생성된 경우, 별칭 검사가 수행되지 않습니다. 그러나 표준 라이브러리 타입의 자기 이동 대입은 객체를 유효한(일반적으로 지정되지 않은) 상태로 만드는 것이 보장됩니다:
std::vector<int> v = {2, 3, 3}; v = std::move(v); // v의 값은 명시되지 않음
예제
#include <iomanip> #include <iostream> #include <string> #include <utility> #include <vector> int main() { std::string str = "Salut"; std::vector<std::string> v; // push_back(const T&) 오버로드를 사용하므로 // str을 복사하는 비용이 발생함 v.push_back(str); std::cout << "After copy, str is " << std::quoted(str) << '\n'; // rvalue 참조 push_back(T&&) 오버로드를 사용하므로 // 문자열이 복사되지 않음; 대신 str의 내용이 // vector로 이동됨. 이는 비용이 적지만 str이 // 비어 있을 수 있음을 의미함 v.push_back(std::move(str)); std::cout << "After move, str is " << std::quoted(str) << '\n'; std::cout << "The contents of the vector are {" << std::quoted(v[0]) << ", " << std::quoted(v[1]) << "}\n"; }
가능한 출력:
After copy, str is "Salut"
After move, str is ""
The contents of the vector are {"Salut", "Salut"}
참고 항목
|
(C++11)
|
함수 인자를 전달하며 템플릿 인자 타입을 사용하여 값 범주를 보존함
(function template) |
|
(C++11)
|
이동 생성자가 예외를 발생시키지 않는 경우 인자를 xvalue로 변환함
(function template) |
|
(C++11)
|
요소들의 범위를 새로운 위치로 이동함
(function template) |