c++ - 함수 - 이동 연산자




std:: move() 란 무엇이며 언제 사용해야합니까? (4)

  1. 이게 뭐야?
  2. 그것은 무엇을합니까?
  3. 언제 사용해야합니까?

좋은 링크를 부탁드립니다.


Q : std::move 란 무엇입니까?

A : std::move() 는 C ++ 표준 라이브러리에서 rvalue 참조로 캐스팅하는 함수입니다.

Simplisticly std::move(t) 는 다음과 같습니다.

static_cast<T&&>(t);

rvalue는 변수에 저장되지 않는 중간 함수 결과와 같이이를 정의하는 표현식을 초과하여 지속되지 않는 임시 변수입니다.

int a = 3; // 3 is a rvalue, does not exist after expression is evaluated
int b = a; // a is a lvalue, keeps existing after expression is evaluated

std :: move ()에 대한 구현은 다음과 같이 N2027 : "Rvalue References에 대한 간략한 소개" 에서 제공됩니다.

template <class T>
typename remove_reference<T>::type&&
std::move(T&& a)
{
    return a;
}

보시다시피 std::move 는 값 ( T ), 참조 유형 ( T& ) 또는 참조 점 ( T&& )으로 호출 되더라도 T&& 반환합니다.

Q : 그것은 무엇을합니까?

A : 캐스트로서 런타임 중에는 아무 것도하지 않습니다. 컴파일시에는 rvalue로 참조를 계속 고려하고 싶다고 컴파일러에게 알리는 것과 관련이 있습니다.

foo(3 * 5); // obviously, you are calling foo with a temporary (rvalue)

int a = 3 * 5;
foo(a);     // how to tell the compiler to treat `a` as an rvalue?
foo(std::move(a)); // will call `foo(int&& a)` rather than `foo(int a)` or `foo(int& a)`

그것이하지 않는 것 :

  • 인수 복사본 만들기
  • 복사 생성자를 호출하십시오.
  • 인수 객체 변경

Q : 언제 사용해야합니까?

A : rvalue (임시 표현식)가 아닌 인수로 이동 의미를 지원하는 함수를 호출하려면 std::move 사용해야합니다.

이렇게하면 다음과 같은 후속 질문이 나옵니다.

  • 이동 의미 란 무엇입니까? Copy semantics와 달리 의미 이동은 다른 개체의 멤버를 복사하는 대신 '인계'를 사용하여 개체의 멤버를 초기화하는 프로그래밍 기술입니다. 이러한 'take over'는 포인터 및 리소스 핸들로만 의미가 있으며, 기본 데이터가 아닌 포인터 또는 정수 핸들을 복사하여 저렴하게 전송할 수 있습니다.

  • 이동 의미를 지원하는 클래스 및 객체의 종류는 무엇입니까? 개발자가 자신의 클래스에서 이동 의미를 구현하는 것은 개발자가 자신의 클래스를 복사하는 대신 전송하는 것이 도움이되는 경우 개발자가 따라야합니다. 일단 이동 시맨틱을 구현하면, 이동 시맨틱을 효율적으로 처리하는 클래스에 대한 지원을 추가 한 많은 라이브러리 프로그래머의 작업을 직접 활용할 수 있습니다.

  • 왜 컴파일러가 스스로 알아낼 수 없습니까? 컴파일러는 그렇게하지 않는 한 함수의 또 다른 오버로드를 호출 할 수 없습니다. 컴파일러가 함수의 일반 버전이나 이동 버전을 호출해야하는지 여부를 선택하도록 도와야합니다.

  • 어떤 상황에서 컴파일러에게 변수를 rvalue로 처리해야한다고 말하고 싶습니까? 이것은 중간 결과가 복구 될 수 있다는 것을 알고있는 템플릿 또는 라이브러리 함수에서 발생할 가능성이 큽니다.


1. "그게 뭐야?"

std::move() 는 기술적으로 함수 인 반면, 실제로 함수가 아닙니다 . 컴파일러가 표현식의 값으로 간주하는 방식 사이의 일종의 변환기 입니다.

2. "무엇을합니까?"

주목해야 할 첫 번째 사실은 std::move() 가 실제로 아무 것도 움직이지 않는다는 것 입니다.

애니메이션 시리즈 Bleach 를 본 적이 있다면 Quincy Seele SchneiderReishi가 부드럽게 됩니다.

진지하게, 그것은 표현을 좌변 값 또는 순수한 평판 값 (당신이 오랫동안 사용하고있는 변수 또는 일시적으로 잠시 동안 주위를 돌아 다니고있는 변수 등)에서 xvalue로 변환 합니다. xvalue는 컴파일러에게 알려줍니다.

당신은 나를 약탈하고, 내가 가지고있는 것을 옮기고 다른 곳에서 그것을 사용할 수 있습니다. (어쨌든 나는 곧 파괴 될 것이기 때문에). "

즉, std::move(x) 를 사용하면 컴파일러가 x 를 식인 할 수 있습니다. 따라서 x 가 자신의 버퍼를 메모리에 가지고 있다면 - std::move() 후에 컴파일러는 다른 객체를 소유 할 수 있습니다.

3. "언제 사용해야합니까?"

이 질문을하는 또 다른 방법은 "기존 객체의 자원을 어떻게 절약 할 수 있습니까?"입니다. 글쎄, 만약 당신이 응용 프로그램 코드를 작성한다면, 아마도 컴파일러에 의해 생성 된 임시 객체를 많이 사용하는 것은 아니다. 따라서 주로 생성자, 연산자 메서드, STL 알고리즘과 유사한 함수 등에서 객체를 만들고 자동으로 삭제하는 등의 작업을 수행합니다. 물론, 그것은 엄지 손가락의 규칙입니다.

일반적으로 복사하는 대신 한 객체에서 다른 객체로 '이동'하는 것이 일반적입니다. @Guillaume http://thbecker.net/articles/rvalue_references/section_01.html 연결되는데 간단한 예가 있습니다.

template <class T>
swap(T& a, T& b) {
    T tmp(a);   // we now have two copies of a
    a = b;      // we now have two copies of b (+ discarded a copy of a)
    b = tmp;    // we now have two copies of tmp (+ discarded a copy of b)
}

move를 사용하면 리소스를 복사하는 대신 리소스를 바꿀 수 있습니다.

template <class T>
swap(T& a, T& b) {
    T tmp(std::move(a));
    a = std::move(b);   
    b = std::move(tmp);
}

T가, 예를 들어 크기 n의 vector<int> 일 때 어떤 일이 일어나는지 생각해보십시오. 첫 번째 버전에서는 3 * n 요소를 읽고 쓰며, 두 번째 버전에서는 기본적으로 벡터의 버퍼에 3 개의 포인터 만 읽고 쓰게됩니다. 물론, 클래스 T는 움직이는 방법을 알아야합니다. 이 작업을 수행하려면 T를위한 이동 할당 연산자와 이동 생성자가 있어야합니다.


복사를하지 않고 다른 곳에있는 객체의 내용을 "전송"해야 할 때 move를 사용할 수 있습니다 (예 : 내용이 중복되지 않아 복사 할 수없는 객체 (예 : unique_ptr)에서 사용할 수있는 이유입니다). 또한 객체가 복사를하지 않고 (그리고 많은 시간을 절약 할) 임시 객체의 내용을 std :: move로 가져올 수도 있습니다.

이 링크는 정말로 나를 도왔습니다.

http://thbecker.net/articles/rvalue_references/section_01.html

내 대답이 너무 늦어서 미안하지만, 나는 또한 std :: move에 대한 좋은 링크를 찾고 있었고, 나는 약간의 "금욕"위에 링크를 발견했다.

이것은 r-value 참조에 중점을 두었습니다.이 참조는 어떤 상황에서 사용해야합니까? 더 자세히 설명했기 때문에 여기에서이 링크를 공유하고 싶습니다.


C ++의 Wikipedia 페이지 11 R- 값 참조 및 생성자 이동

  1. C ++ 11에서는 복사 생성자 외에도 객체가 이동 생성자를 가질 수 있습니다.
    복사 할당 연산자 외에도 이동 할당 연산자가 있습니다.
  2. 객체가 "rvalue-reference"( Type && ) Type && 인 경우 복사 생성자 대신 이동 생성자가 사용됩니다.
  3. std::move() 는 객체에 대한 rvalue-reference를 생성하고 그로부터 이동을 가능하게하는 캐스트입니다.

복사본을 피하는 새로운 C ++ 방법입니다. 예를 들어 이동 생성자를 사용하면 std::vector 는 내부 포인터를 데이터에 복사하여 새 객체에 넣을 수 있으므로 이동 된 객체는 잘못된 상태로 남겨져 모든 데이터를 복사하지 않아도됩니다. 이것은 C ++ 일 것입니다.

이동 의미론, 가치 평가, 완벽한 전달을 위해 인터넷 검색을 해보십시오.





move-semantics