C++11 의 오른쪽 값 참조 와 이동 의 미 를 자세히 설명 합 니 다.

C++11 의 가장 중요 한 특징 은 복사 대상 이 아 닌 이동 할 수 있 는 능력 이다.대상 의 복사 가 발생 하 는 경우 가 많 고,대상 이 복사 한 후 바로 소각 되 는 경우 도 있 으 며,이 경우 복사 대상 이 아 닌 이동 이 성능 을 크게 향상 시 킬 수 있다.

오른쪽 값 과 오른쪽 값 참조
이동 작업 을 지원 하기 위해 새로운 표준 은 새로운 인용 유형 인 오른쪽 값 인용 을 도 입 했 습 니 다.바로 오른쪽 값 에 연결 해 야 하 는 인용 입 니 다.우 리 는&가 아니 라&를 통 해 오른쪽 값 인용 을 얻 을 수 있 습 니 다.오른쪽 값 은 삭제 할 대상 에 만 연결 되 는 중요 한 특성 을 참조 합 니 다.
왼쪽 값 과 오른쪽 값 은 표현 식 의 속성 입 니 다.일부 표현 식 은 왼쪽 값 을 생 성하 거나 요구 하 며,다른 일 부 는 오른쪽 값 을 생 성하 거나 요구 합 니 다.일반적으로 왼쪽 값 표현 식 은 대상 의 신분 을 나타 내 고 오른쪽 값 표현 식 은 대상 의 값 을 나타 낸다.(주 소 를 찾 을 수 있 고 이름 이 있 는 것 이 왼쪽 값 입 니 다.주 소 를 찾 을 수 없 는 이름 없 는 것 이 오른쪽 값 입 니 다.)두 가지 뚜렷 한 차 이 는 왼쪽 값 이 지속 적 인 상태 가 있 고 오른쪽 값 은 글자 상수 이거 나 표현 식 에서 값 을 구 하 는 과정 에서 만 든 임시 대상 이다.
일반적인 인용(왼쪽 값 인용)과 유사 하 며,오른쪽 값 인용 도 한 대상 의 다른 이름 에 불과 하 다.우 리 는 변환 을 요구 하 는 표현 식,문자 상수 또는 반환 값 표현 식 에 왼쪽 값 을 참조 할 수 없고 오른쪽 값 을 왼쪽 값 에 직접 연결 할 수 없습니다.그러나 상수 왼쪽 값 인용 은 비상 왼쪽 값,상수 왼쪽 값,오른쪽 값 에 연결 할 수 있 으 며 만능 인용 유형 입 니 다.그러나 오른쪽 값 이 인용 한 오른쪽 값 을 인용 하 는 것 보다 상수 왼쪽 값 이 인용 한 오른쪽 값 은'여생'에서 만 읽 을 수 있 습 니 다.

int i = 42;
int &r = i;     //r  i
int &r2 = i*2;    //  ,i*2     
int &&rr = i;    //  ,                 
int &&rr2 = i*2;   //  , rr2          
const int &r3 = i*2; //  ,               
변 수 는 연산 대상 만 있 고 연산 자가 없 는 표현 식 으로 볼 수 있 으 며 왼쪽 값 입 니 다.우 리 는 이 변수 가 오른쪽 값 참조 형식 이 더 라 도 오른쪽 값 인용 을 변수 에 직접 연결 할 수 없습니다.단,우 리 는 새로운 표준 라 이브 러 리 의 move 함 수 를 통 해 왼쪽 값 에 연 결 된 오른쪽 값 인용 을 얻 을 수 있 습 니 다.

int &&rr3 = std::move(rr2);
전 환 된 왼쪽 값 은 그 생명주기 가 좌우 에서 의 전환 에 따라 바 뀌 지 않 고 전 환 된 후에 왼쪽 값 을 사용 하면 운행 시 오류 가 발생 할 수 있 음 을 주의해 야 한다.따라서 move 를 호출 하 는 것 은 원래 의 왼쪽 값 변 수 를 할당 하거나 없 애 는 것 을 제외 하고 더 이상 사용 하지 않 겠 다 는 약속 을 의미 합 니 다.그러나 더 많은 경우 에 우 리 는 오른쪽 값 으로 바 꾸 어 인용 해 야 하 는 것 은 생명 주기 가 곧 끝 날 대상 이다.
이동 구조 함수 와 이동 할당 연산 자
사용자 정의 형식 도 모 바 일 작업 을 지원 하기 위해 서 는 모 바 일 구조 함수 와 모 바 일 할당 연산 자 를 정의 해 야 합 니 다.이 두 구성원 은 비슷 한 복사 작업 을 하지만 주어진 대상 에서 자원 을 훔 치 는 것 은 복사 자원 이 아 닙 니 다.복사 구조 함수 와 유사 합 니 다.이동 구조 함수 의 첫 번 째 매개 변 수 는 이 유형의 오른쪽 값 참조 입 니 다.모든 추가 매개 변 수 는 기본 적 인 실제 참조 가 있어 야 합 니 다.자원 이동 을 완성 하 는 것 외 에 이동 구조 함 수 는 이동 후 소스 대상 이 효과 적 이 고 분석 가능 한 상태 에 있 는 지 확인 해 야 한다.

#include <iostream> 
#include <algorithm> 

class MemoryBlock 
{ 
public: 
  //     
  explicit MemoryBlock(size_t length) : _length(length) , _data(new int[length]) {} 

  //      
  ~MemoryBlock() 
  {
    if (_data != nullptr)  delete[] _data;
  } 

  //         
  MemoryBlock& operator=(const MemoryBlock& other) 
  { 
    if (this != &other) 
    { 
      delete[] _data; 
      _length = other._length; 
      _data = new int[_length]; 
      std::copy(other._data, other._data + _length, _data); 
    } 
    return *this; 
  } 

  //        
  MemoryBlock(const MemoryBlock& other) 
    : _length(0) 
    , _data(nullptr) 
  { 
    *this = other; 
  } 

  //        ,                 (          ?)
  MemoryBlock& operator=(MemoryBlock&& other) noexcept
  {
    if (this != &other) 
    {  
      delete[] _data; 
      //     
      _data = other._data; 
      _length = other._length; 
      //              
      other._data = nullptr; 
      other._length = 0; 
    } 
    return *this; 
  }

  //       
  MemoryBlock(MemoryBlock&& other) noexcept
    _data(nullptr) 
    , _length(0) 
  { 
    *this = std::move(other); 
  } 

  size_t Length() const 
  { 
    return _length; 
  } 

private: 
  size_t _length; // The length of the resource. 
  int* _data; // The resource. 
};

하나의 클래스 가 자신의 버 전의 복사 제어 구성원 을 정의 하지 않 고 클래스 의 모든 비 static 데이터 구성원 이 이동 할 수 있 을 때 컴 파일 러 는 모 바 일 구조 함수 가 이동 할당 연산 자 를 합성 할 수 있 습 니 다.컴 파 일 러 는 내장 형식 을 이동 할 수 있다.만약 하나의 유형 에 대응 하 는 이동 조작 이 있다 면 컴 파 일 러 도 이 유형의 구성원 을 이동 할 수 있다.그 밖 에 이동 구조 함수 나 이동 할당 연산 자 를 정의 하 는 클래스 도 자신의 복사 작업 을 정의 해 야 합 니 다.그렇지 않 으 면 이 멤버 들 은 기본적으로 삭제 로 정의 된다.이동 작업 은 다 르 기 때문에 삭제 로 암시 적 으로 정의 되 지 않 습 니 다.그러나 만약 에 우리 가 컴 파 일 러 생 성=defualt 의 이동 조작 을 현저하게 요구 하고 컴 파 일 러 가 모든 구성원 을 이동 할 수 없다 면 컴 파 일 러 는 이동 조작 을 삭제 함수 로 정의 할 것 이다.
만약 에 이동 구조 함수 와 복사 구조 함수 가 있다 면 컴 파일 은 일반적인 함수 일치 규칙 을 사용 하여 어떤 구조 함 수 를 사용 하 는 지 확인 합 니 다.그러나 복사 작업 만 정의 하고 이동 작업 이 정의 되 지 않 으 면 컴 파일 러 는 이동 구조 함 수 를 합성 하지 않 습 니 다.이 때 는 move 를 호출 하여 이동 하 더 라 도 호출 된 복사 작업 입 니 다.

class Foo{
public:
  Foo() = default;
  Foo(const Foo&);
  //          
};
Foo x;
Foo y(x);         //        
Foo z(std::move(x));   //        ,           
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기