>

이동 구성 가능하고 이동 가능하지만 복사 가능 또는 복사 가능하지 않은 (사소한) 클래스가 있다고 가정 해 봅시다.

class movable
{
  public:
    explicit movable(int) {}
    movable(movable&&) {}
    movable& operator=(movable&&) { return *this; }
    movable(const movable&) = delete;
    movable& operator=(const movable&) = delete;
};

이것은 잘 작동합니다 :

movable m1(movable(17));

물론 m1 때문에 작동하지 않습니다.  rvalue가 아닙니다 :

movable m2(m1);

하지만 m1 를 감쌀 수 있습니다   std::move 을 rvalue-reference로 캐스팅하여 작동시킵니다.

movable m2(std::move(m1));

지금까지는 너무 좋아. 이제 단일 값을 보유하는 (사소한) 컨테이너 클래스가 있다고 가정 해 보겠습니다.

template <typename T>
class container
{
  public:
    explicit container(T&& value) : value_(value) {}
  private:
    T value_;
};

그러나 작동하지 않습니다 :

container<movable> c(movable(17));

컴파일러 (clang 4.0과 g ++ 4.7.2를 시도했습니다)는 movable 를 사용하려고한다고 불평합니다. container 에서 삭제 된 복사 생성자 의 초기화 목록. 다시 value 포장   std::move  작동합니다 :

   explicit container(T&& value) : value_(std::move(value)) {}

그러나 왜 std::move 인가  이 경우에 필요합니까? value 아니에요  이미 movable&& 유형 ? value_(value) 는 어떻습니까   movable m1(movable(42)) 와 다른 ?

  • 답변 # 1

    그것은 value 때문입니다  명명 된 변수이므로 lvalue입니다. 와이즈 비즈  다시 rvalue로 캐스트해야 std::move 의 이동 생성자 과부하가 발생합니다.  일치합니다.

    다른 방법으로 말하면 : rvalue 참조는 rvalue에바인딩할 수 있지만 그 자체가 rvalue가 아닙니다. 그것은 단지 참조 일 뿐이며 표현에서는 lvalue입니다. rvalue 인 표현식을 작성하는 유일한 방법은 캐스트입니다.

  • 답변 # 2

    T 와이즈 비즈  

    How is 와 다른 ?

    명명 된 rvalue 참조는 lvalue (따라서 삭제 된 사본 ctor에 바인드 됨) 인 반면 임시는 rvalue (구체적인 prvalue)입니다.

    value_(value)

    와이즈 비즈

    예와 같이 :

    movable m1(movable(42))
    
    

    와이즈 비즈 와이즈 비즈  lvalue입니다.

    위의 인용문은 비 규범적인 주석에서 나온 것이지만, 나머지 5 절은 xems를 만드는(일명)으로 설명하기 때문에 적절한 설명입니다. , 지정된 표현식 만 있고 xvalues를 생성하는 다른 표현식은 없습니다. 전체 목록은 여기를 참조하십시오.

    † xvalue는 rvalue의 한 하위 그룹이며 prvalue는 다른 하위 그룹입니다. 설명은이 질문을 참조하십시오.

    §5 [expr] p6

  • 이전 mysql - 오류 1022 (23000) : 쓸 수 없습니다 테이블 '# sql-2b8_2'의 중복 키
  • 다음 c++ - c ++ 11에서 string - : c_str ()으로 가리키는 배열의 문자를 변경할 수 있습니까?