Herb의 답변 (편집되기 전)은 실제로 움직일 수 없는 유형의 좋은 예를 제공했습니다 std::mutex
..
OS의 기본 뮤텍스 유형 (예 : pthread_mutex_t
POSIX 플랫폼에서)은 객체 주소가 값의 일부임을 의미하는 "위치 불변"이 아닐 수 있습니다. 예를 들어 OS는 초기화 된 모든 뮤텍스 개체에 대한 포인터 목록을 유지할 수 있습니다. std::mutex
데이터 멤버로 기본 OS 뮤텍스 유형 이 포함되어 있고 기본 유형의 주소가 고정되어 있어야하는 경우 (OS가 해당 뮤텍스에 대한 포인터 목록을 유지하기 때문에) std::mutex
네이티브 뮤텍스 유형을 힙에 저장해야합니다. std::mutex
개체 사이를 이동할 때 동일한 위치 또는 std::mutex
이동해서는 안됩니다. 힙에 저장하는 것은 불가능합니다. 왜냐하면 std::mutex
에는 constexpr
생성자가 있고 상수 초기화 (예 : 정적 초기화)에 적합해야 하기 때문 입니다.std::mutex
프로그램의 실행이 시작되기 전에 생성되도록 보장되므로 생성자는 new
. 따라서 남은 유일한 옵션은 std::mutex
움직이지 않는 것입니다.
고정 주소가 필요한 것을 포함하는 다른 유형에도 동일한 추론이 적용됩니다. 자원의 주소가 고정되어 있어야한다면 이동하지 마십시오!
움직이지 않는 것에 대한 또 다른 주장이 있는데 std::mutex
, 그것은 안전하게하는 것이 매우 어렵다는 것입니다. 뮤텍스가 움직이는 순간 아무도 뮤텍스를 잠그려고하지 않는다는 것을 알아야하기 때문입니다. 뮤텍스는 데이터 레이스를 방지하는 데 사용할 수있는 빌딩 블록 중 하나이기 때문에 레이스 자체에 대해 안전하지 않다면 불행 할 것입니다! 움직일 std::mutex
수 없는 것은 일단 생성되고 파괴되기 전에 누구나 할 수있는 유일한 일은 그것을 잠그고 잠금을 해제하는 것이며, 이러한 작업은 명시 적으로 스레드 안전이 보장되고 데이터 경합을 유발하지 않습니다. 이 동일한 인수가 std::atomic<T>
객체에 적용됩니다 . 원자 적으로 이동할 수 없으면 안전하게 이동할 수 없으며 다른 스레드가 호출을 시도 할 수 있습니다.compare_exchange_strong
움직이고있는 순간에 물체에 따라서 유형을 이동할 수 없어야하는 또 다른 경우는 안전한 동시 코드의 저수준 빌딩 블록이고 모든 작업의 원 자성을 보장해야하는 경우입니다. 객체 값이 언제든지 새 객체로 이동 될 수있는 경우 모든 원자 변수를 보호하기 위해 원자 변수를 사용하여 사용하는 것이 안전한지 또는 이동되었는지 알 수 있도록 원자 변수를 사용해야합니다. 그 원자 변수 등등 ...
나는 객체가 값의 보유자 역할을하는 유형이나 값의 추상화 역할을하는 유형이 아닌 순수한 메모리 조각 일 때 그것을 이동하는 것은 의미가 없다고 말하는 것으로 일반화 할 것이라고 생각합니다. int
이동할 수없는 것과 같은 기본 유형 : 이동은 복사 일뿐입니다. 에서 내장을 뜯어 낼 수없고 int
, 그 값을 복사 한 다음 0으로 설정할 수 있지만, 여전히 int
값이 있고 메모리의 바이트 일뿐입니다. 하지만 int
여전히 움직일 수 있습니다복사본이 유효한 이동 작업이므로 언어 용어에서. 그러나 복사 불가능한 유형의 경우 메모리 조각을 이동하고 싶지 않거나 이동할 수없고 해당 값도 복사 할 수없는 경우 이동할 수 없습니다. 뮤텍스 또는 원자 변수는 메모리의 특정 위치 (특수 속성으로 처리됨)이므로 이동이 의미가없고 복사도 불가능하므로 이동할 수 없습니다.