Pass a struct as a function parameter or just use it as a global variable?
-
Yet another one of my favourites - academic questions. Hopefully a decent discussion will follow, but please no more RTFM. Cheers
Unless you have a good, compelling argument otherwise (and there are a few), you should prefer to pass structs as parameters. If its small (e.g. something like a
struct timeval
), and you don't need to modify the members, its OK to pass by value. If its large, then pass by reference (pointer). If you're not going to modify the struct in the function then you should mark the reference as const.struct small_obj {
char description[16];
int count;
}; // size = 20 bytesstruct large_obj {
char text[1024][1024];
double factor[1024][1024];
}; // size = 9 MBvoid f1(small_obj arg); // OK, puts 20 bytes on the stack, f1 gets a copy
// of the struct. Any modifications to the struct are
// local ot f1void f2(small_obj* arg); // stack is 4 bytes only. changes to f2 members will not
// be seen by callervoid f3(const small_obj *arg); // stack is 4 bytes only. attempts within f3 to modify members
// should produce compiler warningsvoid f4(small_obj& arg); // similar to f2(), but uses C++ reference type
void f5(const small_obj& arg); // similar to f3, but uses C++ reference type
void f6(large_obj arg); // questionable. This copys 9 MB onto the stack, which might
// be more than the OS can handle, and might incur performance
// penalties you can avoid by passing as a pointer or referenceThe problem with global values, especially global values that are not local to a single file (e.g. declared as static), is it becomes increasingly more difficult to reason about where the variable gets modified. Given a function say
print_item(void)
you might not expect your global Item to get modified, but print_item() calls foo(void), which calls bar(void) which calls frobnicate(void), which modifies Item. If you are trying to trace down a bug, trying to see where Item gets modified can be difficult. On the other hand, calling print_item(const Item&), you can be (more or less) sure that Item doesn't get modified during the lifetime of print_item() (more or less because print_item() could be nasty and cast away constness, but that's an evil for another tale). Alternatively, you might have print_item(Item foo), which gets a local copy of Item, so the caller knows that whatever changes print_item might make to its copy, the callers Item remains unchan -
Unless you have a good, compelling argument otherwise (and there are a few), you should prefer to pass structs as parameters. If its small (e.g. something like a
struct timeval
), and you don't need to modify the members, its OK to pass by value. If its large, then pass by reference (pointer). If you're not going to modify the struct in the function then you should mark the reference as const.struct small_obj {
char description[16];
int count;
}; // size = 20 bytesstruct large_obj {
char text[1024][1024];
double factor[1024][1024];
}; // size = 9 MBvoid f1(small_obj arg); // OK, puts 20 bytes on the stack, f1 gets a copy
// of the struct. Any modifications to the struct are
// local ot f1void f2(small_obj* arg); // stack is 4 bytes only. changes to f2 members will not
// be seen by callervoid f3(const small_obj *arg); // stack is 4 bytes only. attempts within f3 to modify members
// should produce compiler warningsvoid f4(small_obj& arg); // similar to f2(), but uses C++ reference type
void f5(const small_obj& arg); // similar to f3, but uses C++ reference type
void f6(large_obj arg); // questionable. This copys 9 MB onto the stack, which might
// be more than the OS can handle, and might incur performance
// penalties you can avoid by passing as a pointer or referenceThe problem with global values, especially global values that are not local to a single file (e.g. declared as static), is it becomes increasingly more difficult to reason about where the variable gets modified. Given a function say
print_item(void)
you might not expect your global Item to get modified, but print_item() calls foo(void), which calls bar(void) which calls frobnicate(void), which modifies Item. If you are trying to trace down a bug, trying to see where Item gets modified can be difficult. On the other hand, calling print_item(const Item&), you can be (more or less) sure that Item doesn't get modified during the lifetime of print_item() (more or less because print_item() could be nasty and cast away constness, but that's an evil for another tale). Alternatively, you might have print_item(Item foo), which gets a local copy of Item, so the caller knows that whatever changes print_item might make to its copy, the callers Item remains unchanThanks, you may have answered my other problem. ( I'll posting it soon.) At this point I use struct sort-off attached to a class. Not static. I am saying sort-off because the main code is OpenGL and it does not work well in C++ class. I do not foresee any other code to modify it. But for learning experience I'll go with passing the struct via pointer to the function which is also "passed" as parameter to another function. Pretty convoluted , mostly because OpenGL "pipe" architecture. But so far it id working as expected.