2012-01-10 143 views
2

所以我對編程/ C++還是比較陌生,仍然試圖圍繞着指針並通過引用和所有事物傳遞。我試圖找出一個程序現在需要將一個結構數組傳遞給另一個函數。我只是直接將數組傳遞給了它。它似乎工作正常。然而,我所關心的是我相信我是通過價值傳遞它的,並且我明白最好通過引用來傳遞結構,所以你不會每次都複製一個結構體......在C++中通過引用傳遞一個結構體數組

不管怎樣,下面是我在做什麼一個基本的例子:

struct GoldenHelmet { 
    int foo; 
    string bar; 
    }; 

void pass (GoldenHelmet ofMambrino[], int size); 

int main() { 
    GoldenHelmet ofMambrino[10]; 
    int size = sizeof(ofMambrino)/sizeof(ofMambrino[0]); 
    ofMambrino[1].foo = 1; 
    pass(ofMambrino, size); 
    cout << ofMambrino[2].foo << endl; 
    return 0; 
} 

void pass (GoldenHelmet ofMambrino[], int size) { 
    ofMambrino[2].foo = 100; 
    ofMambrino[2].bar = "Blargh"; 
} 

從我的理解,它的工作原理是因爲數組已經指針,對不對?但我配置的方式,我仍然將結構的副本和一切傳遞給pass()函數?我試圖通過引用來傳遞它,但它似乎並不想以我嘗試過的任何方式工作。

+4

數組不是指針。重複這個過程直到你暈倒,然後回到這個網站去閱讀當時發佈的答案。 – 2012-01-10 04:13:38

+3

@NiklasBaumstark不,答案將在C++ :) – dasblinkenlight 2012-01-10 04:14:07

+0

@Kerrek SB謝謝澄清。我正在閱讀[這篇文章](http://forums.devshed.com/c-programming-42/how-to-passing-arrays-of-structures-61159.html),它似乎暗示着數組是指針。我想我需要繼續關注它。無論如何,現在要閱讀回覆,感謝大家的幫助。 – Nate 2012-01-10 04:20:01

回答

5

這句法:

void pass (GoldenHelmet ofMambrino[], int size) 

其實相當混亂。因爲你沒有傳遞一個數組,所以你正在傳遞一個指針。儘管如此,他們不是一回事,不要感到困惑。這種古怪只適用於功能參數。以上內容與此完全相同:

void pass (GoldenHelmet * ofMambrino, int size) 

實際上不可能通過值傳遞數組,除非它是另一個對象的子對象。您可以通過引用傳遞,你需要,雖然有大小,但你可以做到這一點使用模板:

template<int N> 
void pass (GoldenHelmet (&ofMambrino)[N]) 
+1

爲什麼我們需要一個模板? 'void pass(GoldenHelmet(&h)[10])'有什麼問題? – 2012-01-10 04:19:06

+0

@Kerrek:我沒有說你需要一個模板。我說過「你需要包括尺寸,但你可以使用模板來做到這一點」。你選擇了明確它的大小,我選擇了使用模板。 – 2012-01-10 04:22:00

+1

@Benjamin謝謝,這開始變得更有意義。所以如果我傳遞一個指針而不是整個數組,我真的需要擔心通過引用傳遞它嗎?如果我只是單純地傳遞一個結構體,我可以看到通過引用傳遞的好處。但是如果我只是傳遞指針,他們真的對傳遞引用有任何好處? – Nate 2012-01-10 04:23:01

1

數組表示並作爲指針傳遞,因此您不在此處複製任何內容。相反,如果您通過單一struct,它將被傳遞值。

下面是一個代碼段,說明這最後一點:

void passByVal (GoldenHelmet ofMambrino) { 
    ofMambrino.foo = 100; 
    ofMambrino.bar = "Blargh"; 
} 

void passByRef (GoldenHelmet& ofMambrino) { 
    ofMambrino.foo = 100; 
    ofMambrino.bar = "Blargh"; 
} 

int main() { 
    GoldenHelmet h; 
    passByVal(h); // h does not change 
    passByRef(h); // fields of h get assigned in the call 
} 
6

的C++方法:

#include <array> 

typedef std::array<GoldenHelmet, 10> Helmets; 

void pass(Helmets &); 

int main() 
{ 
    Helmets h; 
    h[1].foo = 1; 
    pass(h); 
    //... 
} 

void pass(Helmets & h) 
{ 
    h[2].foo = 100; 
    // ... 
} 

事實上,我們通過引用傳遞數組。

4

這些都是可能的,但他們都不是按值傳遞。試想一下ofMambrino是數組開頭的地址,這就是你傳遞的。

void pass (GoldenHelmet ofMambrino[], int size) 
void pass (GoldenHelmet ofMambrino[10], int size) 
void pass (GoldenHelmet *ofMambrino, int size) 
void pass (GoldenHelmet (&ofMambrino)[10], int size) 
+0

完美,這清理了很多。它也解釋了爲什麼我需要傳遞大小,因爲如果我只是指向數組開頭的地址,我需要跟蹤數組的長度。 – Nate 2012-01-10 04:31:33

+0

@Nate:的確,當我第一次開始學習時,我總是想知道爲什麼沒人告訴我「它只是地址」。 – 2012-01-10 04:39:23

0

首先數組不是指針。我們將其作爲參數列表中的指針,因爲當我們使用

int x[ ] 

x實際上是指向數組的開始的常量指針。當你將這個傳遞給一個函數時,你發送了數組開頭的內存的地址。這就是爲什麼當你改變你的函數時,你實際上在調用者部分的變量的地址上做了改變。這是真實的模擬呼叫,不作參考。但是,由於您正在處理內存位置,所以效果與通過引用的調用相同。出於這個原因,當你發送你的結構數組時,你實際上傳遞了你的結構數組的地址。這就是爲什麼當你改變這個價值時,你實際上改變了你的結構。

要參照使用電話,有一件事你必須做的是確定樣

void f(int &param) 

和調用函數時,它一樣的是他人的函數原型。

總結:

int main() 
{ 
    int x; 

    // simulated call by reference that use adress of variable, 
    // lets say adress of x is 19ff 
    f(&x);  // actually you send 19ff 

    f(x);  // call by reference that use reference of variable 

} 

// simulated call by reference 
void f(const int *y) 
{ 
    // when you use like *y=10, you are writing on memory area 19ff, you actually 
    // change memory area that is belong to x in the main 

} 

// call by reference 
void f(const int &y) 
{ 
}