IT TIP

x = std :: move (x) 정의되지 않았습니까?

itqueen 2020. 12. 1. 20:20
반응형

x = std :: move (x) 정의되지 않았습니까?


x이전에 초기화 된 어떤 유형의 변수가 되자 . 다음 줄입니다.

x = std::move(x)

찾으시는 주소가 없습니다? 이것은 표준에서 어디에 있으며 그것에 대해 무엇을 말합니까?


아니요, 이것은 정의되지 않은 동작이 아니며 구현 정의 동작이 될 것입니다. 이동 할당이 구현되는 방식에 따라 다릅니다.

이것과 관련이있는 것은 LWG 2468 호 : 라이브러리 유형의 자체 이동 할당입니다. 이것은 활성 문제이며 공식적인 제안이 없으므로 결정적인 것이 아니라 지시적인 것으로 간주되어야하지만 관련된 섹션을 지적합니다. 표준 라이브러리에 대해 현재 충돌을 지적합니다. 그것은 말한다 :

우리가 쓴다고 가정하자

vector<string> v{"a", "b", "c", "d"};
v = move(v);

v 상태는 무엇이어야합니까? 표준은 자기 이동 할당에 대해 구체적으로 언급하지 않습니다. 표준의 여러 부분에 관련 텍스트가 있으며이를 조정하는 방법이 명확하지 않습니다.

[...]

어떤 것이 우선권을 갖는지 명확하지 않기 때문에이 조각들을 모으는 방법은 본문에서 명확하지 않습니다. 17.6.4.9 [res.on.arguments]가이기거나 (MoveAssignable 요구 사항에 언급되지 않은 암시 적 전제 조건을 부과하므로 v = move (v)가 정의되지 않음) 또는 23.2.1 [container.requirements.general ] 승리 (일반적으로 라이브러리 함수에 대해 보장되는 것 이상으로 Container :: operator =에 대한 추가 보장을 명시 적으로 제공하므로 v = move (v)는 작동하지 않음) 또는 다른 것일 수도 있습니다.

내가 확인한 기존 구현에서 가치가 무엇인지에 대해 v = move (v)는 벡터를 지우는 것처럼 보였습니다. 벡터를 변경하지 않고 그대로 두지 않았고 충돌을 일으키지 않았습니다.

그리고 제안합니다 :

비공식적으로 : MoveAssignable 및 컨테이너 요구 사항 테이블 (및 이동 할당을 언급하는 기타 요구 사항 테이블 (있는 경우))을 변경하여 x = move (x)가 정의 된 동작이고 x가 유효하지만 지정되지 않은 상태로 남도록합니다. 그것은 아마도 오늘날 표준이 말하는 것은 아니지만 아마도 우리가 의도 한 것이고 우리가 사용자에게 말한 것과 구현이 실제로하는 것과 일치 할 것입니다.

빌트인 타입의 경우 이것은 기본적으로 사본입니다. C ++ 14 표준 섹션 5.17 [expr.ass] 초안에서 볼 수 있습니다 .

단순 할당 (=)에서 표현식의 값은 왼쪽 피연산자가 참조하는 객체의 값을 대체합니다.

수업의 경우와는 다릅니다 5.17.

왼쪽 피연산자가 클래스 유형이면 클래스가 완료됩니다. 클래스의 개체에 대한 할당은 복사 / 이동 할당 연산자 (12.8, 13.5.3)에 의해 정의됩니다.

clang에는 자체 이동 경고가 있습니다 .

로그 : Clang에 새 경고 -Wself-move를 추가합니다.

-Wself-move는 -Wself-assign과 유사합니다. 이 경고는 값을 자신으로 이동하려고 할 때 트리거됩니다. 이 경고와 함께 발견되었을 버그에 대해서는 r221008을 참조하십시오.


를 호출 X::operator = (X&&)하므로이 경우를 관리하는 것은 구현에 달려 있습니다 (에서 수행 한대로 X::operator = (const X&)).


하는 것은 호출 X::operator=(X&&)(lvalue 정규화 된 " *this"사용)입니다.

기본 유형에서는 std::move관심이 거의 없으며 전혀 상호 작용하지 않습니다 =. 따라서 이것은 클래스 유형의 객체에만 적용됩니다.

이제 내부 std(또는 템플릿 중 하나에 의해 생성 된) 유형의 경우 개체 moved from은 지정되지 않은 (아직 유효한) 상태로 남아있는 경향이 있습니다. 이것은 정의되지 않은 동작은 아니지만 유용한 동작은 아닙니다.

주어진 각각의 의미를 X::operator=(X&&)조사해야 할 것입니다. 내부의 모든 유형을 조사 std하는 것은 스택 오버플로 답변에 대해 "너무 광범위"합니다. 그들은 심지어 자신과 모순 될 수도 있습니다.

일반적으로 move객체에서 수신 할 때 "이후 객체가 어떤 상태에 있는지는 신경 쓰지 않는다"고 소비자에게 전달합니다. a의 사용은 x = std::move(x)당신이 (보통)으로, 이렇게 무례 어떤 상태 관리 x(당신이 그것에 할당 될 때) 동작 완료 후입니다. 동일한 작업 내에서 lvalue 및 rvalue로 동일한 객체를 사용하고 있으며 이는 좋은 습관이 아닙니다.

흥미로운 예외는 std::swap다음과 같은 default입니다 .

template<class T>
void swap(T& lhs, T& rhs) {
  T tmp = std::move(lhs);
  lhs = std::move(rhs);
  rhs = std::move(tmp);
}

중간 선 은 동일한 객체에서 swap을 두 번 호출 lhs = std::move(rhs)하면 수행 x = std::move(x)됩니다.

그러나이 x줄이 완료된 후 어떤 상태인지 신경 쓰지 않습니다 . 우리는 이미 xin 의 상태를 저장 tmp했으며 다음 줄에서 복원 할 것입니다.

참고 URL : https://stackoverflow.com/questions/31547466/is-x-stdmovex-undefined

반응형