[英]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.