[英]C: Passing Struct to a Function doesn't result in a call by value operation
我在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
的原始结构将引用相同的值。
如果要按值传递这些对象,则需要自己进行深层复制,在其中分配新矩阵,并将原始矩阵中的所有值复制到其中。
正如Drew所指出的,在C ++中,实现深度复制的首选方法是通过复制构造函数 。 复制构造函数允许您在按值传递对象时执行深层复制,而无需自己显式复制对象。
如果你还没有为类和构造函数做好准备,你可以简单地编写一个函数,也就是Spielfeld copySpielfeld(Spielfeld original)
,它将执行那个深层复制; 它基本上与您在示例中省略的初始化代码相同,除了它将从传入的Spielfeld
获取值,而不是创建新的Spielfeld
。 您可以在将field
传递给show
函数之前调用它,或者让show
函数为传入的任何参数执行此操作,具体取决于您希望API如何工作。
您在传递fieldToShow
时正在复制指针。 按值传递不执行深层复制,因此在调用show(...)
和main(...)
(尽管不同)时Spielfeld
具有相同的Matrix 值 。
解决这个问题并非易事。 可能最简单的方法是将show(...)
更改为pass-by-reference(基本上使用Spielfeld*
)并在函数的开头创建一个显式副本。
复制Spielfeld对象时:
因此,对副本助行器内容的修改不会影响原件,因为它们具有不同的助行器。 对副本矩阵内容的修改会影响原始内容,因为它们共享相同的矩阵。
结构以值开始传递,但由于它包含指针(矩阵),因此指针所指向的内容可由有权访问该结构的任何人更改。 如果您不希望发生这种情况,可以使指针成为常量。
作为有趣的琐事:这是按值调用java的方式。 对象引用始终按值传递。 如果你操纵这些引用所指向的对象很难,那么就会觉得通过引用调用了。
真的与你的问题无关,但也许你发现了这个问题。
快乐的黑客
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.