I have the following problem with a program which I wrote in Visual C++ and I hope that anyone can help me please:
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';
}
When you pass the structure in, you are passing it in by value. However, the matrix within it is implemented as a pointer to pointer to int. Those pointers are references, and so when you modify the value referenced by them in your function, the same value is referenced by the original structure in
main.If you want to pass these objects by value, you need to do a deep copy yourself, in which you allocate a new matrix, and copy all of the values from the original matrix into it.
As Drew points out, in C++, the preferred way to implement that deep copy is via a copy constructor. A copy constructor allows you to perform your deep copy any time your object is passed by value, without having to explicitly copy the object yourself.
If you are not ready for classes and constructors yet, you can simply write a function, perhaps
Spielfeld copySpielfeld(Spielfeld original), that will perform that deep copy; it will essentially be the same as your initialization code that you elided in your example, except it will take values from theSpielfeldpassed in, instead of creating a newSpielfeld. You may call this before passing yourfieldinto theshowfunction, or have theshowfunction do it for any argument passed in, depending on how you want your API to work.