2012-01-10 327 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) 
{ 
}