es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué un destructor explícitamente predeterminado deshabilita el constructor de movimiento predeterminado?

¿Por qué un destructor explícitamente predeterminado deshabilita el constructor de movimiento predeterminado en la clase? Sé que lo hace, como se explica en varias respuestas existentes (por ejemplo: https://stackoverflow.com/questions/56968443/explicitly-defaulted-destructor-disables-default-move-constructor-in-a-class?noredirect=1&lq=1).

Quiero saber por qué: ¿cuál es la justificación para esto, cuando en realidad no hace nada que implique que el constructor de movimiento pueda necesitar código personalizado? De hecho, recomendamos que la gente use “= default” en lugar de un cuerpo vacío porque de esa manera el compilador sabe que no hace nada más allá de las acciones automáticas, exactamente como si hubiera sido generado automáticamente sin ninguna declaración.

Para ser realmente claro, sé por qué definir un destructor con tu propia lógica en él debería suprimir la autogeneración. Estoy señalando que “= default” no cambia nada en comparación con dejar que el compilador lo genere implícitamente, por lo que esa razón no se aplica aquí.

Recuerdo que hace más de 10 años hubo mucha discusión sobre cuál es la forma correcta de especificarlo. No recuerdo si alguna vez aprendí por qué se decidió de esa manera al final. ¿Alguien conoce alguna razón convincente por la que esta sea una característica específica deseable en sí misma, o alguna razón técnica por la que deba ser así?

demostración: https://gcc.godbolt.org/z/86WGMs7bq

“`c++
#include
#include
#include
#include

struct C
{
std::string s;
C () : s{“default ctor”} {}
// ~C() = default; // <<< comentar esta línea, y veremos que original.s ha “robado” su contenido
// <<< con este destructor declarado, la cadena original se copia.
};

int main()
{
C original;
original.s = “valor cambiado”;
C other { std::move(original) };
using std::cout;
cout << “original ahora: ” << original.s << ‘\n’;
cout << “otro es: ” << other.s << ‘\n’;
}
“`

Esta regla se establece en cppreference y fue mencionada el otro día en un video de conferencia de C++ que acaba de publicarse, lo que me recordó de esto.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La razón por la cual un destructor explícitamente predeterminado deshabilita el constructor de movimiento predeterminado en una clase es para evitar comportamiento indeseable. Al definir explícitamente un destructor, la clase puede tener lógica personalizada de limpieza que debe ser ejecutada cuando se destruye un objeto.

    Si el constructor de movimiento todavía se permitiera ser generado implícitamente, podría mover recursos en la clase (como memoria asignada dinámicamente) sin limpiar adecuadamente los recursos en el objeto original. Esto podría resultar en una situación donde varios objetos tienen una referencia al mismo recurso, lo que lleva a un comportamiento indefinido cuando se destruyen uno o más de los objetos.

    Al deshabilitar el constructor de movimiento predeterminado, la clase obliga al programador a definir un constructor de movimiento, aunque simplemente se reenvíe al constructor de movimiento predeterminado. Esto asegura que cualquier lógica personalizada de limpieza en el destructor se ejecute adecuadamente cuando se mueve un objeto.

    En la práctica, se recomienda usar = predeterminado para el destructor para evitar cualquier sobrecarga innecesaria o efecto secundario. Sin embargo, si se requiere un destructor con lógica personalizada, el constructor de movimiento también debe definirse explícitamente para asegurar una gestión adecuada de recursos.

Comments are closed.