|
Passing struct array by reference |
AceBlkwell
Member #13,038
July 2011
|
All, I'm working on a program. My goal in the coding is to pass various structs to initialization functions. To do this I want to pass them by reference. So far I can't figure out how to pass an array of structures by reference. I've searched the web and have tried trial & error. No luck. In the example below I get... invalid initialization of reference of type 'Cards&' from expression of type 'Cards [8]' match_config(sCards); 1#include <cstdio>
2#include <cstdlib>
3#include <iostream>
4
5/********************* DEFINES ******/
6#define LIMIT 8
7
8
9/********************* STRUCTS ******/
10struct Cards {
11
12 bool bMatched;
13 bool bFlipped;
14 char cValue;
15 int iX;
16 int iY;
17 int iBdPosition;
18};
19
20/********************* FUNCTION DECLARE ******/
21int random_no(int);
22void match_config(Cards & sCards);
23
24
25
26int main(int argc, char *argv[]){
27
28 Cards sCards[LIMIT];
29 match_config(sCards);
30 return 0;
31
32} //end main()
33
34void match_config (Cards & sCards){
35
36 int setup[LIMIT];
37 int hold = 0;
38 int check = 0;
39 char card = 'A';
40 int matches = 0;
41 int fchoice = 0;
42 int schoice = 0;
43
44 for(int count = 0;count<8;count++){
45 hold = random_no(8);
46 for(int a_count=0;a_count<8;a_count++){
47 if(hold == setup[a_count]){
48 check = 1;
49 count--;}//end if
50 }//inner for
51 if(check == 0)
52 setup[count]=hold;
53 check = 0;
54
55 }// end outer for
56
57 for(int count = 0;count<8;count++){
58 if(count !=0 && count % 2 == 0)
59 card++;
60 sCards[1].cValue = card;
61 sCards[1].bMatched ='N';
62 }//for outer
63
64 std::cout<<"Match Board "<<std::endl;
65 for(int count = 0;count<4;count++)
66 std::cout<<count+1<<" ";//end for 0-3
67 std::cout<<std::endl;
68 for(int count = 4;count<8;count++)
69 std::cout<<count+1<<" ";//end for 4-7
70 std::cout<<std::endl;
71
72
73} //end of match_config()
|
DanielH
Member #934
January 2001
|
Arrays are funny that way. In your code, you are passing one Cards, not an array of Cards. // one Cards void match_config(Card & sCards) {} I would just pass sCards as a pointer. sCards is already a pointer. You might have declared it as an array, but it's a pointer. // pointer to array void match_config(Cards* sCards) {} //or supply a length if your length is not defined elsewhere like it is with LIMIT void match_config(Cards* sCards, size_t len) {} If you REALLY want to pass by reference, void match_config(Cards (&sCards)[]) {} // or void match_config(Cards (&sCards)[LIMIT]) {} As before, if LIMIT is not defined globally then you could do something like this void match_config(Cards (&sCards)[], size_t len) {}
|
torhu
Member #2,727
September 2002
|
Since you're using C++, it would make sense to use std::vector or the new std::array and pass that by reference instead of dealing with plain arrays and pointers. |
DanielH
Member #934
January 2001
|
That too. std::vector<VARTYPE> vector; std::array<VARTYPE,ARRAYSIZE> array; They are nearly identical. One difference is with an array, the size is specified in the beginning. It cannot be resized. Vectors can be resized and will as you modify it. Other difference is the internal memory: The address of an array's memory does not change once it is created. However, every time a vector is resized, it has to allocate memory in another location and then copy all the data from the first location to the second. |
Dizzy Egg
Member #10,824
March 2009
|
OOP anyone!? Could get this all done with a class??
---------------------------------------------------- |
AceBlkwell
Member #13,038
July 2011
|
Thanks All, You know with so many ways to accomplish this, you would think I would have stumbled across one of them on my own. Thanks Again. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Prefer pointers to references. When using a reference it isn't always clear that the object isn't local. Also, don't return a reference or pointer to a stack object. That would go out of scope and leave you with a dangling pointer. When using a pointer, you have to specify that it is an address - &data and it is clear that it can be modified. If you have to, use a const& , a constant reference. This is safe, and the compiler will catch many errors this way. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Kitty Cat
Member #2,815
October 2002
|
Presuming you're using a modern version of C++, you can also use a span (C++20). void match_config(std::span<Cards> sCards); // Or if you want a fixed/compile-time size: void match_config(std::span<Cards,LIMIT> sCards); (note it's not passed by reference or pointer; it is the pointer). -- |
AceBlkwell
Member #13,038
July 2011
|
Thanks All. I agree reference is more confusing as it looks like a local variable. I'll have to consider that. I've never heard of span but will look into it. |
DanielH
Member #934
January 2001
|
For simple structs (containing only primitive variables) pass as value. If it is complex or you need to reference the struct (treat as a pointer) then pass as reference. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
DanielH said: If it is complex or you need to reference the struct (treat as a pointer) then pass as reference. No, you should really pass it as a pointer, for the reasons I mentioned above. The asterisk reminds you it's special and you can modify the object. Otherwise you might forget you're working with a reference. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
DanielH
Member #934
January 2001
|
Don't forget. That's on you. Pass by reference! |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Making things simpler and less likely to cause problems is a #1 skill in programming. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
DanielH
Member #934
January 2001
|
Yes, that's why pass by reference. I prefer to keep the variable the same form. If it's a pointer, pass by pointer. If not, pass by reference. I'm just messing you. Do what you want and let's agree to disagree. |
Polybios
Member #12,293
October 2010
|
Edgar Reynaldo said: Prefer pointers to references. When using a reference it isn't always clear that the object isn't local. No. - Do pass by reference! If it is not some POD that be better passed as value anyways. References cannot be nullptr / NULL and you can't do nasty stuff with them as with pointers. If there are problems tracking what is a local variable and what is an argument, it's quite likely that your functions / methods are just too long. Only use pointers when you have to. Prefer const references to non-const references. If transferring ownership, then move (Type &&someStuff / std::move) happily. |
|