La respuesta de hierba (antes de que fuera editado) en realidad le dio un buen ejemplo de un tipo que no debe ser móvil: std::mutex.
El tipo de mutex nativo del sistema operativo (por ejemplo, pthread_mutex_ten plataformas POSIX) podría no ser "invariante de ubicación", lo que significa que la dirección del objeto es parte de su valor. Por ejemplo, el sistema operativo puede mantener una lista de punteros a todos los objetos mutex inicializados. Si std::mutexcontiene un tipo de mutex del sistema operativo nativo como miembro de datos y la dirección del tipo nativo debe permanecer fija (porque el sistema operativo mantiene una lista de punteros a sus mutex), entonces cualquiera de std::mutexlos dos tendría que almacenar el tipo de mutex nativo en el montón para que permaneciera en la misma ubicación cuando se mueve entre std::mutexobjetos o std::mutexno debe moverse. No es posible almacenarlo en el montón, porque a std::mutextiene un constexprconstructor y debe ser elegible para una inicialización constante (es decir, una inicialización estática) para questd::mutexse garantiza que se construirá antes de que comience la ejecución del programa, por lo que su constructor no puede usarlo new. Entonces, la única opción que queda es std::mutexser inamovible.
El mismo razonamiento se aplica a otros tipos que contienen algo que requiere una dirección fija. Si la dirección del recurso debe permanecer fija, ¡no la mueva!
Hay otro argumento para no moverse, std::mutexque es que sería muy difícil hacerlo de manera segura, porque necesitaría saber que nadie está tratando de bloquear el mutex en el momento en que se está moviendo. Dado que los mutexes son uno de los bloques de construcción que puedes usar para prevenir las carreras de datos, ¡sería desafortunado si no estuvieran a salvo contra las propias carreras! Con un inmueble, std::mutexusted sabe que lo único que cualquiera puede hacerle una vez que se ha construido y antes de que se haya destruido es bloquearlo y desbloquearlo, y esas operaciones están explícitamente garantizadas para ser seguras y no introducir carreras de datos. Este mismo argumento se aplica a los std::atomic<T>objetos: a menos que se puedan mover atómicamente, no sería posible moverlos con seguridad, otro hilo podría estar intentando llamarcompare_exchange_strongen el objeto justo en el momento en que se mueve. Por lo tanto, otro caso en el que los tipos no deberían ser móviles es donde son bloques de construcción de bajo nivel de código concurrente seguro y deben garantizar la atomicidad de todas las operaciones en ellos. Si el valor del objeto se pudiera mover a un nuevo objeto en cualquier momento, necesitaría usar una variable atómica para proteger cada variable atómica para que sepa si es seguro usarlo o si se ha movido ... y una variable atómica para proteger esa variable atómica, y así sucesivamente ...
Creo que generalizaría para decir que cuando un objeto es solo un recuerdo puro, no un tipo que actúa como titular de un valor o abstracción de un valor, no tiene sentido moverlo. Tipos fundamentales como intno poder mover: moverlos es solo una copia. No puede extraer las agallas de un int, puede copiar su valor y luego establecerlo en cero, pero sigue intsiendo un valor, solo son bytes de memoria. Pero unint todavía es móvilen los términos del lenguaje porque una copia es una operación de movimiento válida. Sin embargo, para los tipos que no se pueden copiar, si no quiere o no puede mover la pieza de memoria y tampoco puede copiar su valor, entonces no es móvil. Un mutex o una variable atómica es una ubicación específica de la memoria (tratada con propiedades especiales), por lo que no tiene sentido moverse, y tampoco es copiable, por lo que no se puede mover.