2

我用 Visual C++ 编写的程序遇到以下问题,希望任何人都可以帮助我:

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';
}
4

5 回答 5

9

当您传入结构时,您是按值传入它。但是,其中的矩阵被实现为指向 int 指针的指针。这些指针是引用,因此当您在函数中修改它们引用的值时,相同的值会被main.

如果要按值传递这些对象,则需要自己进行深度复制,在其中分配一个新矩阵,并将原始矩阵中的所有值复制到其中。

正如 Drew 指出的,在 C++ 中,实现深拷贝的首选方式是通过拷贝构造函数。复制构造函数允许您在任何时候通过值传递对象时执行深度复制,而不必自己显式复制对象。

如果您还没有准备好使用类和构造函数,您可以简单地编写一个函数,也许Spielfeld copySpielfeld(Spielfeld original),它将执行该深层复制;它基本上与您在示例中省略的初始化代码相同,除了它将从Spielfeld传入的值中获取值,而不是创建一个新的Spielfeld. 您可以在将您的参数传递给函数之前调用它fieldshow或者让show函数为传入的任何参数执行此操作,具体取决于您希望 API 如何工作。

于 2010-01-08T17:45:56.967 回答
3

当你通过时,你正在复制指针fieldToShow。值传递不执行深度复制,因此Spielfeld调用show(...)main(...)(尽管不同)对于 Matrix 具有相同的

解决这个问题并非易事。可能最简单的做法是更改show(...)为按引用传递(Spielfeld*基本上使用 a)并在函数开头进行显式复制。

于 2010-01-08T17:41:44.820 回答
2

当您的 Spielfeld 对象被复制时:

  • 副本有自己的“步行者”,是原版“步行者”的复制品。由于 walker 是一个结构,这意味着您有两个结构。
  • 副本有自己的“Matrix”成员,它是原始“Matrix”成员的副本。但是 Matrix 是一个指针,这意味着你有两个指针。指针的副本指向原始指向的同一事物。

所以,对副本的walker内容的修改不会影响到原来的,因为他们有不同的walker。对副本矩阵内容的修改确实会影响原始矩阵,因为它们共享相同的矩阵。

于 2010-01-08T17:44:18.407 回答
1

该结构是按值传递的,但是由于它包含一个指针(矩阵),因此该指针所指向的内容可以被任何有权访问该结构的人更改。如果您不希望这种情况发生,您可以将指针设为 const。

于 2010-01-08T17:41:33.120 回答
0

作为有趣的琐事:这就是 java 中按值调用的工作方式。对象引用总是按值传递。如果你操纵这些引用指向的对象,就会感觉就像发生了引用调用。

与您的问题实际上无关,但也许您觉得这很有趣。

快乐的黑客

于 2010-01-08T18:30:47.220 回答