¿Estoy en lo correcto al decir que necesito eliminar el puntero en destructor?
Al diseñar un objeto como este, primero debe responder la pregunta: ¿El objeto posee la memoria apuntada por ese puntero? Si es así, entonces obviamente el destructor del objeto necesita limpiar esa memoria, entonces sí necesita llamar a delete. Y esta parece ser tu intención con el código dado.
Sin embargo, en algunos casos, es posible que desee tener punteros que se refieren a otros objetos cuya vida se supone que debe ser administrada por otra cosa. En ese caso, no desea llamar a eliminar porque es deber de alguna otra parte del programa hacerlo. Además, eso cambia todo el diseño posterior que va al constructor de copias y al operador de asignación.
Voy a proceder a responder el resto de las preguntas bajo el supuesto de que usted quiere que cada objeto TreeNode tenga la propiedad de los objetos izquierdo y derecho.
¿Es esta la forma correcta de implementar el constructor predeterminado?
No. Usted necesita para inicializar los left
y right
punteros a NULL (0 o si lo prefiere). Esto es necesario porque los punteros no identificados podrían tener cualquier valor arbitrario. Si su código alguna vez construye un TreeNode por defecto y luego lo destruye sin asignarle nada a esos punteros, se invocará delete en cualquier valor inicial. Entonces, en este diseño, si esos punteros no apuntan a nada, entonces debe garantizar que estén configurados en NULL.
¿Cómo asignar la variable de puntero en el constructor de copia? La forma en que escribí en Copy Constructor puede ser incorrecta.
La línea left = new TreeNode();
crea un nuevo objeto TreeNode y establece left
para que apunte a él. La línea left = node.left;
reasigna ese puntero para apuntar a cualquier objeto TreeNode al que apunta node.left
. Hay dos problemas con eso.
Problema 1: Ahora nada apunta a ese nuevo TreeNode. Se pierde y se convierte en una pérdida de memoria porque nada puede destruirlo.
Problema 2: Ahora tanto left
como node.left
terminan apuntando al mismo TreeNode. Eso significa que el objeto que se está copiando y el objeto desde el que toma los valores creerán que poseen ese mismo TreeNode y ambos invocarán eliminar en sus destructores. Llamar a eliminar dos veces en el mismo objeto es siempre un error y causará problemas (incluso posibles bloqueos o daños en la memoria).
Dado que cada TreeNode posee sus nodos izquierdo y derecho, entonces probablemente lo más razonable es hacer copias. Por lo que iba a escribir algo similar a:
TreeNode::TreeNode(const TreeNode& node)
: left(NULL), right(NULL)
{
data = node.data;
if(node.left)
left = new TreeNode(*node.left);
if(node.right)
right = new TreeNode(*node.right);
}
¿Es necesario aplicar el mismo código (a excepción de retorno) para ambos constructor de copia y operatior =?
Casi seguro. O al menos, el código en cada uno debería tener el mismo resultado final. Sería muy confuso si la construcción y la asignación de copias tuvieran efectos diferentes.
EDITAR - El párrafo anterior debe ser: El código en cada uno debe tener el mismo resultado final en que los datos se copian del otro objeto. Esto a menudo implicará un código muy similar. Sin embargo, el operador de asignación probablemente deba verificar si ya se ha asignado algo al left
y right
, así que límpielos. Como consecuencia, es posible que también tenga que tener cuidado con la autoasignación o escribir de una manera que no cause que nada malo suceda durante la autoasignación.
De hecho, hay formas de implementar una utilizando la otra para que el código real que manipula las variables miembro solo se escriba en un lugar. Otras preguntas sobre SO han discutido eso, como this one.
Es necesario asignar una cadena vacía a '' data' en su constructor TreeNode', ya que el constructor por defecto de 'std :: string' va a hacer eso sí mismo. –
El constructor de copias y el operador de asignación tienen una semántica de copia ligeramente diferente. Eso es muy confuso para los usuarios de tu clase. – sbi
hola sbi, ¿Quiere decir que debería usar la copia exacta del mismo código tanto para el constructor de copias como para el operador? –