Pregunta

Tengo el siguiente problema con un programa que he escrito en Visual C ++ y espero que alguien me puede ayudar por favor:

typedef struct spielfeld
{
 int ** Matrix;
 int height; 
 int width; 
 Walker walker;
 Verlauf history;
} Spielfeld;

void show(Spielfeld fieldToShow); //Prototype of the Function where I have this
                                  //problem

int main(int argc, char *argv[])
{
  int eingabe;
  Spielfeld field;

  //Initialize .. and so on

  //Call show-Function and pass the structure with Call by Value
  show(field);
  //But what's happened? field.Matrix has changed!!
  //can anyone tell me why? I don't want it to become changed!
  //cause that's the reason why I pass the field as Call by Value!
}

void show(Spielfeld fieldToShow)
{
 //Here is the problem: Alltough the parameter fieldToShow has been passed
 //with call by value, "fieldToShow.Matrix[0][0] = 1" changes the field in 
 //main!!
 fieldToShow.Matrix[0][0] = 1;

 //Another try: fieldToShow.walker.letter only affects the local fieldToShow, 
 //not that field in main! That's strange for me! Please help!
 fieldToShow.walker.letter  = 'v';
}
¿Fue útil?

Solución

Cuando se pasa en la estructura, está de paso en términos de valor. Sin embargo, la matriz dentro de ella se implementa como un puntero a puntero a int. Esas referencias son punteros, y así cuando se modifica el valor al que hace referencia en su función, el mismo valor se hace referencia a la estructura original en main.

Si desea pasar estos objetos de valor, lo que necesita hacer una profunda copiar a sí mismo, en la que se puede asignar una nueva matriz, y copiar todos los valores de la matriz original en ella.

Como dibujó señala, en C ++, la forma preferida de poner en práctica que copia profunda es a través de un href="http://en.wikipedia.org/wiki/Copy_constructor" rel="nofollow constructor de copia . Un constructor de copia le permite realizar su copia en profundidad cualquier momento su objeto se pasa por valor, sin tener que copiar explícitamente el objeto mismo.

Si usted no está listo para las clases y constructores sin embargo, sólo tiene que escribir una función, tal vez Spielfeld copySpielfeld(Spielfeld original), que llevará a cabo esa copia profunda; que, esencialmente, será el mismo que el código de inicialización que elididas en su ejemplo, excepto que tomará los valores de la Spielfeld pasado en lugar de crear una nueva Spielfeld. Usted puede llamar a esto antes de pasar su field en la función show, o tienen la función show lo haga por cualquier argumento pasado en, dependiendo de cómo quiere que su API para trabajar.

Otros consejos

Usted está copiando el puntero cuando se pasa fieldToShow. El paso por valor no realizar una copia profunda, por lo tanto el Spielfeld en una invocación de show(...) y main(...) (aunque sean distintos) tienen el mismo valor de la matriz.

La fijación de este no es trivial. Probablemente la cosa más fácil de hacer sería cambiar show(...) pasar por referencia (utilizando un Spielfeld* básicamente) y hacer una copia explícita al comienzo de la función.

Cuando el objeto se copia Spielfeld:

  • La copia tiene su propio "Walker", que es una copia de la de la original "walker". Desde Walker es una estructura, que significa que tiene dos estructuras.
  • La copia tiene su propio miembro de "Matrix", que es una copia del miembro de la "matriz" de la original. Sin embargo, la matriz es un puntero, lo que significa que tiene dos punteros. Una copia de un puntero apunta a lo mismo a los puntos originales.

Por lo tanto, las modificaciones en el contenido del andador de la copia no afectará a la original, porque tienen diferentes caminantes. Las modificaciones en el contenido de la matriz de la copia afectan el original, ya que comparten la misma matriz.

La estructura se empiezan pasa por valor, pero ya que contiene un puntero (la matriz) lo que el puntero está apuntando a se puede cambiar por cualquier persona que tenga acceso a la estructura. Si no desea que esto ocurra, se puede hacer que el puntero const.

Como curiosidades interesantes: así es como llamar por obras de valor en Java. Objeto referencias siempre se pasan por valor. Si se manipulan los objetos a los que estas referencias apuntan dura que se sentirá como sucedió llamada por referencia.

realmente no tiene nada que ver con su pregunta, pero tal vez usted encontrará que interestring.

Happy piratería

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top