Passing an array of structs by reference in C++ - c++

So I'm still rather new to programming/C++, and still trying to wrap my head around pointers and passing by reference and everything. A program I'm trying to figure out now needs to pass an array of structs to another function. I've gotten it working by just passing the array directly there. It seems to work fine. However, what I'm concerned about is that I believe I'm passing it by value, and I understand that it's better to pass structs by reference, so you're not making a copy of the struct every time...
Anyway, here's a basic example of what I'm doing:
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";
}
From what I understand, it works because arrays are already pointers, right? But the way I have that configured, am I still passing a copy of the struct and everything to the pass() function? I've tried to pass it by reference, but it doesn't seem to want to work any way I've tried.

The C++ way:
#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;
// ...
}
Indeed, we pass the array by reference.

This syntax:
void pass (GoldenHelmet ofMambrino[], int size)
is actually quite confusing. Because you are not passing an array, you are passing a pointer. They are not the same thing though, don't get confused. This oddity only applies to function parameters. The above is exactly identical to this:
void pass (GoldenHelmet * ofMambrino, int size)
It's actually impossible to pass an array by value, unless it is a sub-object of another object. You can pass them by reference, you need to include the size though, but you can do that using a template:
template<int N>
void pass (GoldenHelmet (&ofMambrino)[N])

These are all possible, but none of them are pass by value. Just think of ofMambrino as being the address of the beginning of the array, and that is what you are passing.
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)

Arrays are represented and passed as pointers, so you are not copying anything here. In contrast, if you were passing a single struct, it would be passed by value.
Below is a code snippet to illustrate this last point:
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
}

First of all array is not pointers. We refer this as a pointer in the argument list because when we use
int x[ ]
x is actually const pointer that points the beginning of the array. And when you pass this to a function you send the adress of the memory that is beginning of the array. Thats why when you make a change in your function, you make change in the adress of your variable in the caller section actually. This is actualy simulated call by reference not call by reference. But effect is same with call by reference because you are working on memory locations. For this reason when you send array of your struct you pass actually adress of your array of structs. Thats why when you change value on this, you actually change your structs.
To use call by reference, one thing you must to do is to define your function prototype like
void f(int &param)
and when calling function, it is same with the others.
To summarize:
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)
{
}

Related

Pointer to Pointer Memory-address [duplicate]

Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.

Trouble passing a whole structure array to a function

I'm sort of new to C++ and programming in general. I'm making a pokemon remake of the old gameboy version for fun, and I'm having trouble passing a whole structure as an arguement.
This is a shortened version to highlight the problem I'm having:
struct Enemy_Pokeman
{
string opp_name;
int num_pokeman;
int pokeman_LVL;
};
void pl_Pokeman(Enemy_Pokeman);
void pokeman_data(string opp_name, int num_pokeman, int pokeman_ID[], int pokeman_LVL[],
int purpose)
{
Enemy_Pokeman enemypokeman[num_pokeman];
enemypokeman[0].opp_name = opp_name;
enemypokeman[0].num_pokeman = num_pokeman;
for(int i=0; i<num_pokeman; i++)
enemypokeman[i].pokeman_LVL = pokeman_LVL[i];
pl_Pokeman(enemypokeman); //Function call - Codeblocks detects error
//on this line
}
void pl_Pokeman(Enemy_Pokeman enemy)
{
cout << endl;
}
Sorry if this doesn't make sense, I didn't want to post the entire thing, so I chopped it up a bit.
The problem is that it won't accept Enemy_Pokeman as an arguement.
Function pl_Pokeman only takes Enemy_Pokeman type while you passed in an array of Enemy_Pokeman
You update pl_Pokeman function to take array as input:
void pl_Pokeman(Enemy_Pokeman enemy[], int arraySize);
Or
template<typename T, size_t N>
void pl_Pokeman(Enemy_Pokeman (&enemy)[N])
you're passing to your function whole array of Enemy_Pokemans, not just one element. function expects one element only. also, you're creating that array within a function, so it's a local variable. if function pokemon_data returns, that array will be destroyed.
For Single structure-
When you are passing the structure as a argument, you should pass with & operator.
pl_Pokeman(&enemypokeman); // Fix 1
While catching it you need to catch it with Structure pointer.
void pl_Pokeman(Enemy_Pokeman *); // Fix 2
For Array of structure-
pl_Pokeman(&enemypokeman,size); // pass it with size
while catching it
void pl_Pokeman(Enemy_Pokeman (*)[], int );

Assigning pointer to a different address in function

just curious what is the explanation of this?
void f(int * x);
int test = 100;
int main()
{
int z = 35;
int * a = &z;
f(a);
cout<<*a;
..
}
void f(int *x)
{
x = &test;
}
We are taught we can use pointers inside function arguments if we want to modify the "outside" object (as a in this case). But x = &test does not do much, and the cout still prints 35.
I know *x =someVal would work though in f().
In C pointers are passed by value just like ints, floats, etc. So if you want to modify it and have that modification be visible outside of the function call, you need to pass a pointer to the thing you want to modify, in this case that's a pointer to a int pointer:
void f(int **x) {
*x = &test;
}
However, in C++ passing a reference is a much better approach:
void f(int*& x) {
x = &test;
}
If you labeled the question C, what you taught it would be acceptable. For C++ it is techically correct but morally wrong, you should pass by reference to modify the object, not fiddling with pointer and address.
In your code you get what you coded for: pass a pointer and then reassign that poitner's value. That is not visible outside the function. What you intended to do is
void f(int *x)
{
*x = 42;
}
and the C++ version would be like:
void f(int &x)
{
x = 42;
}
int main()
{
int z = 35;
f(z);
cout << z;
}
Due to recommendation of one of the members I am adding my own answer which I derived from the other peoples responses. So thanks go to them.
Basically the problem in my code was that I was changing a copy of my pointer.
The only thing x in function f and the value a passed to f have in common is the address where they point to.

How to pass Virtually Anything To A Function In C++ (or C)?

I need to pass something like a pointer that takes anything as a function parameter. You know, something without any predefined type or a type that can take anything like this:
void MyFunc( *pointer );
And then use it like:
char * x = "YAY!";
MyFunc(x);
int y = 10;
MyFunc(&y);
MyObj *b = new MyObj();
MyFunc(b);
And I don't want to use templates because I am mostly using C in my project.
Is there anything that can be used here except a function macro?
In C++, Boost.Any will let you do this in a type-safe way:
void func(boost::any const &x)
{
// any_cast a reference and it
// will throw if x is not an int.
int i = any_cast<int>(x);
// any_cast a pointer and it will
// return a null pointer if x is not an int.
int const *p = any_cast<int>(&x);
}
// pass in whatever you want.
func(123);
func("123");
In C, you would use a void pointer:
void func(void const *x)
{
// it's up to you to ensure x points to an int. if
// it's not, it might crash or it might silently appear
// to work. nothing is checked for you!
int i = *(int const*)x;
}
// pass in whatever you want.
int i = 123;
func(&i);
func("123");
You seem adverse to it but I'll recommend it anyway: if you're using C++, embrace it. Don't be afraid of templates. Things like Boost.Any and void pointers have a place in C++, but it is very small.
Update:
Well , I am making a small signals - slots - connections library to be
used with my gui toolkit. So that I can get rid of the Ugly WNDPROC. I
need these pointers for the connections.
If you need multi-target signals, Boost.Signals already provides a full and tested signals/slots implementation. You can use Boost.Bind (or std::bind, if you've got a C++0x compiler) to connect member functions:
struct button
{
boost::signal<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click.connect(std::bind(&my_window::handle_click,
this, std::placeholders::_1));
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
If you only want a simple callback, Boost.Function (or std::function if you've got a C++0x compiler) will work well:
struct button
{
std::function<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click = std::bind(&my_window::handle_click,
this, std::placeholders::_1);
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
You can use a function that takes a void*, but you must be aware of the pointer types that are not compatible with void*:
pointers to functions:
void MyFunc(void*);
MyFunc(&MyFunc); // WRONG
pointers to members:
void MyFunc(void*);
struct A { int x; };
MyFunc(&A::x); // WRONG
While these pointers are not compatible with void* (even with casting, on some compilers), they are themselves data. So you can pass a pointer to the pointer:
void MyFunc(void*);
void (*pfn)(void*) = &MyFunc;
MyFunc(&pfn); // ok
struct A { int x; };
int A::*px = &A::x;
MyFunc(&px); // ok
You can define the method as taking one void * argument. Of course, at that point, it's up to you to figure out what to do with the data (as far as accessing it or casting it.)
void MyFunc(void * ptr);
You could use:
void MyFunc( void* p){}
int g = 10;
MyFunc( (void*)&g );
void * is the way to do it. You can assign any pointer type to and from a void *. But to use the pointer in the called function, you'll have to know the type so you can create an appropriate local pointer or cast appropriately. You can encode a limited set of types as enum symbols, and perhaps use a switch to select type-specific behavior. But without a specific purpose or use-case, you might end up chasing your tail in a quest for generality for which C was never intended.
Another way would be to make a union to contain all the various types you know are needed.
typedef union {
int i;
char c;
float f;
} vartype;
Then if the value can carry around its own type-identifier, it becomes a tag-union or variant-record.
typedef struct {
enum type { INT, CHAR, FLOAT } type;
vartype var;
} varrec;

To what use is multiple indirection in C++?

Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.