C/Visual C - SOCORRO_operator+_destructor_inevitable

 
Vista:

SOCORRO_operator+_destructor_inevitable

Publicado por daniel (9 intervenciones) el 28/03/2006 02:28:42
Primero me gustaría saludar a todos los que hacen posible que funcione esta página y a los que le dan vida a ella.

Bueno yo realizo la sobrecarga del operador de suma, pero cuando lo quiero devolver como se llama de forma "inevitable" al destructor al perder el ámbito sale el error _BLOCK_TYPE_IS_VALID:

cVector cVector::operator+(cVector operando2)
{
int i;
float valor;
int exito;

cVector resultado(dimension);

for(i=0;i<dimension;i++)
{
operando2.getValor(i, valor, exito);
if((datos[i].ocupado==1)&&(exito))
resultado.setValor(i,datos[i].valor + valor);
}

return (resultado);
}

He sobrecargado el operador de asignación, pero no sirve de nada pues antes llama al destructor.

¿Cómo podría solucionarlo?

Muchas gracias todos,

Daniel
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:SOCORRO_operator+_destructor_inevitable

Publicado por fernando.gomez (1603 intervenciones) el 28/03/2006 02:52:45
Hola,

para solucionar esto, tendrías que regresar un cVector* y emplear el operador new:

cVector* cVector::operator+(cVector operando2)
{
int i;
float valor;
int exito;

cVector* resultado = new cVector(dimension);

for(i=0;i<dimension;i++)
{
operando2.getValor(i, valor, exito);
if((datos[i].ocupado==1)&&(exito))
resultado->setValor(i,datos[i].valor + valor);
}

return (resultado);
}

Ahora, ¿por qué no regresas una referencia a this? Si el operador + hicieses que operara sobre sí mismo, no tendrías este problema...

cVector& cVector::operator+(cVector operando2)
{
int i;
float valor;
int exito;

for(i=0;i<dimension;i++)
{
operando2.getValor(i, valor, exito);
if((datos[i].ocupado==1)&&(exito))
this->setValor(i,datos[i].valor + valor);
}

return (*this);
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:SOCORRO_operator+_destructor_inevitable

Publicado por daniel (9 intervenciones) el 28/03/2006 10:21:17
Muchas gracias Fernando.

Es que me había bloqueado y no podía seguir.

Gracias.

Un cordial saludo,

Daniel
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:SOCORRO_operator+_destructor_inevitable

Publicado por chuidiang (73 intervenciones) el 30/03/2006 04:57:51
Hola:

Si así te funciona, estupendo, pero debes saber un par de cosillas para evitar efectos desagradables.

Si implementas la solución que devuelve un puntero, imagina que a,b,c,d son variables de tipo cVector, no puedes hacer esto

a=b+c+d;

ya que c+d devuelve un cVector * y no un cVector. Tendrías que redefinir un operator+ con cVector * de parametro. Tambien, al encadenar así, cada operator+() hace un new del que no puedes hacer delete (¿donde haces el delete del resultado parcial que devuelve c+d)?. Es decir, según vas haciendo sumas, vas consumiendo memoria.

En cuanto a devolver la referencia, también tiene un problema secundario. Si haces

a=b+c;

b va a cambiar su contenido, ya que se está sumando c a sí mismo. Si eres consciente de eso y te vale, pues no hay más que hablar, pero es un comportamiento un poco extraño para una suma, en que el sumando se cambia.

La forma correcta es la que tenías tú en principio. El problema es que si cVector tiene atributos que son punteros, debes además redefinir el operador copia. Este es un constructor de este estilo

cVector (cVector &original)
{
}

y aquí haces una copia de todos los atributos, pero haciendo new de los que sean punteros, de forma que el orginal y la copia NO compartan los datos.

Sigue....
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:SOCORRO_operator+_destructor_inevitable

Publicado por chuidiang (73 intervenciones) el 30/03/2006 05:07:53
Si tienes una clase normal, sin atributos que sean punteros, C++ sabe hacer una copia de ella sin problemas, copia los atributos y ya está. No deberías tener problemas con tu operator+

Sin embargo, si alguno de los atributos es un puntero, C++ simplemente hace que en la copia el puntero apunte a los mismos datos que el original. En tu operator +, al perder el ámbito, se destruye el resultado. Si tienes bien hecho el destructor, liberaras los datos de los atributos puntero del resultado. La copia, que es la que sale fuera para el operador de asignación, tiene punteros apuntando a cosas que ya no están y fallan.

Por el mismo motivo, debes redefinir el operator= para que haga sus propios new de los atributos.

En resumen, cuando haces

a=b+c

el b::operator + crea un resultado local con la suma de b+c
C++ llama al constructor copia para sacar fuera de oparator+ ese resultado
C++ llama a.operator= para asignar el resultado a a

tanto el constructor copia como operator= deben hacer new de los atributos que sean punteros (además de asignar los atributos que no sean punteros).

Se bueno.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:SOCORRO_operator+_destructor_inevitable

Publicado por daniel (9 intervenciones) el 30/03/2006 08:24:33
Hola chuidiang.

Primero agradecerte las respuestas que has publicado.

El problema es el que tú bien comentas, pues el resultado de aplicar la función "operator+" se vuelca en una variable local, por tanto cuando pierde el ámbito dicho variable se llama automáticamente al destructor siguiendo los siguientes pasos:

1) Si tenemos la instrucción "return( resultado)"

2) Primero se llama al destructor para liberar el espacio ocupado por resultado, ya que éste realmente tiene propiedades que se reservaron de forma dinámica.

3) A continuación ejecuta el "return", pero como antes lo ha liberado devolvería una dirección de memoria que ya realmente no pertenece al proceso ( vamos daría un mensaje de violación de acceso a memoria)

Entonces la solución que me planteas es sobrecargar el operador de asignación ("operator=" algo que ya tenía hecho). Pero probaré si creando un constructor copia consigo que devuelva ese return una copia del resultado local.

Muchísimas gracias.

Un cordial saludo,

Daniel Leyva
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:SOCORRO_operator+_destructor_inevitable

Publicado por chuidiang (73 intervenciones) el 30/03/2006 10:29:31
Hola:

Es como dices, pero entre el paso 1) y el paso 2) C++ hace una copia del resultado utilizando el operador copia. Esta copia es la que sale fuera para ser asignada por medio del operator=.

El problema es el que te comenté. Si no hay constructor copia, los atributos que sean punteros son compartidos entre el resultado que desaparece y la copia. La copia "sale" teniendo sus punteros sin datos válidos.

Se bueno.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:SOCORRO_operator+_destructor_inevitable

Publicado por daniel (9 intervenciones) el 30/03/2006 23:04:40
Muchas gracias.

Seguramente tendré que realizar un constructor copia y no usar el constructor copia de oficio.

Gracias.

Un saludo,

Daniel
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar