본문 바로가기

C++/STL 및 기타

Move Semantic

Move Semantics (이동 문법)

  • 이동 생성자와 이동 할당 연산자를 구현한 클래스를 move semantic 을 갖고 있다고 한다.
  • 변수(이름으로 참조 할 수 있는 데이터)는 깊은 복사를 하고, 임시값(이름으로 참조 할 수 없는 데이터)이 데이터를 전송한다는 컨셉
  • 객체에 대한 메모리 소유권을 이동시키면서 댕글링 포인터, 메모리 릭을 방지 ( (해제된 메모리를 가리키고 있는 것을 댕글링 포인터라고 한다.)
  • 불필요한 복사를 줄일 수 있다. 벡터 같은 컨테이너에 원소 복사시 유용하게 쓰인다.
    • 객체를 컨테이너에 가져 올 때, 객체 복제가 아닌 이동시킬 수 있다.
    • 임시 객체를 리턴할 때도, 일반 복제 대입 연산 대신에 이동 연산을 이용한다..

lvalue , rvalue

  • lvalue : 주소값을 취할 수 있는 값. 표현식의 왼쪽 오른쪽 모두 될수 있음
  • rvalue : 주소값을 취할 수 없는 값

예시

  • int x = 3;
    • x 는 lvalue, 3 은 rvalue
  • int &r_x = x;
    r_x 는 lvalue 레퍼런스(r_x 도 lvalue 임.)
    레퍼런스는 lvalue 만 가질 수 있음
  • const int &a = 3
    const T & 타입 한에서만, rvalue도 레퍼런스로 받을 수 있음
    const 레퍼런스는 임시로 존재하는 객체값 참조만 할 뿐 변경은 할 수 없기 때문에 가능함.

Rvalue 레퍼런스

int&& data;

  • 위와 같은 것을 rvalue 레퍼런스 라 함
  • rvalue는 아니고, ravlue 를 참조하는 lvalue 임
  • const &T 타입도 rvalue를 참조할 수 있지만, 해당 타입은 값은 수정할 수 없음. 이런 경우를 해결하기 위해 만든 듯

이동 생성자

  class vector {

      vector(vector&& v)
           : my_size(v.my_size), data(v.data)
      {
          v.my_size = 0;
          v.data = 0; //pointer 의 경우 nullptr 대입
      }

  }
  • 이동 생성자는 원본에서 데이터를 가져오고, 원본 데이터는 빈 상태로 둔다.
  • rvalue 로 함수에 전달한 객체는 함수 반환 뒤 만료됐다고 간주한다.
    • 이게 무슨말인가 했는데 , 이런 것 같다.
      vector v1(foo()); //foo는 임시 객체를 반환 한다.

이동 할당 연산자

    class vector {
        vector& operator=(vector&& src)
          {
              assert(my_size == 0 || my_size == src.my_size);
              std::swap(data, src.data);
              return *this;
          }
    }

vector v1; //v1 은 빈 값을 가지고 있어야 한다.
v1 = foo(); //foo() 는 임시 객체를 반환한다. 이 임시 객체를 v2 라 해보자

이동 할당 연산자는 v1 이 v2 의 값을 가지게 하고, v2는 빈 값을 가리키게 해준다.

복사 생략

  • 실제 컴파일러는 최적화를 통해 이동 생성자를 호출하지 않는다. 이를 복사 생략이라 한다. (Copy Elision)
  • vector v1(foo()); //foo 는 임시 객체인 v2를 return
    위와 같은 상황에서 컴파일러는 v2를 생성하고 v1 으로 이동시키는 대신,
    v1 을 생성하고 거기서 모든 연산을 바로 수행한다. 복사(또는) 이동 생성자를 호출하지 않는다고 한다.
    진짜 안불린다.

std::move

  • lvalue 를 rvalue 로 이동한다.
    • 그냥 변수를 임시 변수인것처럼 한다! 이 말은 즉, 이동 가능하게 만들어 준다는 것
  • vector x(std::move(w));
    • 이동 생성자가 호출된다. x는 w의 데이터를 가지게 되고, w 는 빈 값을 가지게 된다.
    • 이동 생성자를 따로 정의해 주지 않으면, w의 값은 변하지 않는 듯 하다.
  • v = std::move(u);
    • 이동 할당 연산자가 호출된다.

'C++ > STL 및 기타' 카테고리의 다른 글

c++ idiom  (0) 2020.09.19
vector  (0) 2020.08.05