C:将 Struct 传递给 Function 不会导致按值调用操作
-
19-09-2019 - |
题
我用 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';
}
解决方案
在传递的结构中,要在由值传递给它。然而,在其中的矩阵被实施为一个指针指向int的指针。这些指针引用,所以当你修改他们在你的函数引用的值,同样的值由main
原有结构引用。
如果你想按值传递这些对象,你需要做一次深层复制自己,在你分配一个新的矩阵,以及所有从原来的矩阵的值复制到它。
作为德鲁指出,在C ++中,优选的方式来实现该深层副本是经由拷贝构造。副本构造函数允许你执行你的深拷贝你的对象是按值传递的任何时间,而不必自己显式复制的对象。
如果您还没有准备好类和构造函数的是,你可以简单地编写一个函数,也许Spielfeld copySpielfeld(Spielfeld original)
,将执行深拷贝;这将基本上是一样的,你在你的例子省略的初始化代码,但它会从传入的Spielfeld
值,而不是创建一个新的Spielfeld
。你可以通过你的field
到show
函数之前调用此方法,或者有show
功能做在传递的任何说法,这取决于你想怎么你的API来工作。
其他提示
当您通过fieldToShow
你复制指针。通过按值不执行深层副本,所以无论是在Spielfeld
和show(...)
的调用的main(...)
(虽然不同)具有相同的值矩阵
修复,这是不平凡的。可能是最简单的事是改变show(...)
通过按引用(使用Spielfeld*
基本上),并在功能的开始作出一个明确的副本。
当您的 Spielfeld 对象被复制时:
- 副本有自己的“行者”,是原作“行者”的复制品。由于 walker 是一个结构体,这意味着您有两个结构体。
- 副本有自己的“Matrix”成员,它是原始“Matrix”成员的副本。但 Matrix 是一个指针,这意味着你有两个指针。指针的副本指向原始指针所指向的同一对象。
因此,对副本步行者内容的修改不会影响原始步行者,因为它们具有不同的步行者。对副本矩阵内容的修改确实会影响原始矩阵,因为它们共享相同的矩阵。
的结构开始值传递,但由于它包含一个指针(矩阵)是什么指针指向可以由任何人可以访问的结构而改变。如果你不希望这种情况发生,可以使指针常量。
有趣的琐事:这是如何在Java价值的作品调用。对象的引用总是由值来传递。如果你要处理这些引用指向艰难的对象,会感觉如呼叫引用发生了。
真的无关,与你的问题,但也许你会发现interestring。
快乐黑客