Understanding declaration in C++ - c++

I am reading C++ in easy steps and came across a piece of code for references and pointers that I do not understand.
The code is void (* fn) (int& a, int* b) = add;. As far as I know it does not affect the program itself but would like to know what this code does.
#include <iostream>
using namespace std;
void add (int& a, int* b)
{
cout << "Total: " << (a+ *b) << endl;
}
int main()
{
int num = 100, sum = 200;
int rNum = num;
int* ptr = &num;
void (* fn) (int& a, int* b) = add;
cout << "reference: " << rNum << endl;
cout << "pointer: " << *ptr << endl;
ptr = ∑
cout << "pointer now: " << *ptr << endl;
add(rNum, ptr);
return 0;
}

Use the spiral rule:
+----------------------+
| +--+ |
| ^ | |
void (* fn ) (int& a, int* b) = add;
^ | | |
| +-----+ |
+---------------------------+
fn is a pointer to a function taking two arguments (an int& named a and a int* named b) and returning void. The function pointer is copy initialized with the free function add.
So where in your code you have:
add(rNum, ptr);
That could be equivalently replaced by:
fn(rNum, ptr);

fn is a pointer to a function taking, from left to right, an int&, and an int*, that does not return anything.
You are assigning the function add to fn.
You could call the function add through the pointer, using exactly the same syntax as you would if you were use add.
One use of this technique is in the modelling of callback functions. For example, qsort requires a callback function for the sorting predicate. Function pointers are more common in C than in C++ where there are other techniques such as function objects, templates, lambdas, and even std::function.

If you read about the clockwise/spiral rule the declaration is easy to decipher:
You declare a variable fn, which is a pointer, to a function, taking some arguments and returning nothing.
Then you make this function-pointer fn point to the add function.
You can then use the function-pointer instead of calling add directly.

void (* fn) (int& a, int* b) = add; declares a function pointer named fn that points that points to a function that has a signature of void(int&,int*). it then intilizes the pointer to the add() function.

Such complicated declarations are easily read using the right-left rule, which works even when the clockwise spiral rule fails, which does even in case of something as simple as int* a[][10].
void (* fn) (int& a, int* b);
Start with the identifier fn and go from right to left, with the parenthesis flipping the direction. So fn is a pointer to a function taking are reference to int and a pointer to int and the function's return type is void.
It's called reading boustrophedonically :) See this answer for another example.

Related

Get output from void function in another void function C++ [duplicate]

I am trying to understand how to use reference parameters. There are several examples in my text, however they are too complicated for me to understand why and how to use them.
How and why would you want to use a reference? What would happen if you didn't make the parameter a reference, but instead left the & off?
For example, what's the difference between these functions:
int doSomething(int& a, int& b);
int doSomething(int a, int b);
I understand that reference variables are used in order to change a formal->reference, which then allows a two-way exchange of parameters. However, that is the extent of my knowledge, and a more concrete example would be of much help.
Think of a reference as an alias. When you invoke something on a reference, you're really invoking it on the object to which the reference refers.
int i;
int& j = i; // j is an alias to i
j = 5; // same as i = 5
When it comes to functions, consider:
void foo(int i)
{
i = 5;
}
Above, int i is a value and the argument passed is passed by value. That means if we say:
int x = 2;
foo(x);
i will be a copy of x. Thus setting i to 5 has no effect on x, because it's the copy of x being changed. However, if we make i a reference:
void foo(int& i) // i is an alias for a variable
{
i = 5;
}
Then saying foo(x) no longer makes a copy of x; i is x. So if we say foo(x), inside the function i = 5; is exactly the same as x = 5;, and x changes.
Hopefully that clarifies a bit.
Why is this important? When you program, you never want to copy and paste code. You want to make a function that does one task and it does it well. Whenever that task needs to be performed, you use that function.
So let's say we want to swap two variables. That looks something like this:
int x, y;
// swap:
int temp = x; // store the value of x
x = y; // make x equal to y
y = temp; // make y equal to the old value of x
Okay, great. We want to make this a function, because: swap(x, y); is much easier to read. So, let's try this:
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
This won't work! The problem is that this is swapping copies of two variables. That is:
int a, b;
swap(a, b); // hm, x and y are copies of a and b...a and b remain unchanged
In C, where references do not exist, the solution was to pass the address of these variables; that is, use pointers*:
void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int a, b;
swap(&a, &b);
This works well. However, it's a bit clumsy to use, and actually a bit unsafe. swap(nullptr, nullptr), swaps two nothings and dereferences null pointers...undefined behavior! Fixable with some checks:
void swap(int* x, int* y)
{
if (x == nullptr || y == nullptr)
return; // one is null; this is a meaningless operation
int temp = *x;
*x = *y;
*y = temp;
}
But looks how clumsy our code has gotten. C++ introduces references to solve this problem. If we can just alias a variable, we get the code we were looking for:
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
int a, b;
swap(a, b); // inside, x and y are really a and b
Both easy to use, and safe. (We can't accidentally pass in a null, there are no null references.) This works because the swap happening inside the function is really happening on the variables being aliased outside the function.
(Note, never write a swap function. :) One already exists in the header <algorithm>, and it's templated to work with any type.)
Another use is to remove that copy that happens when you call a function. Consider we have a data type that's very big. Copying this object takes a lot of time, and we'd like to avoid that:
struct big_data
{ char data[9999999]; }; // big!
void do_something(big_data data);
big_data d;
do_something(d); // ouch, making a copy of all that data :<
However, all we really need is an alias to the variable, so let's indicate that. (Again, back in C we'd pass the address of our big data type, solving the copying problem but introducing clumsiness.):
void do_something(big_data& data);
big_data d;
do_something(d); // no copies at all! data aliases d within the function
This is why you'll hear it said you should pass things by reference all the time, unless they are primitive types. (Because internally passing an alias is probably done with a pointer, like in C. For small objects it's just faster to make the copy then worry about pointers.)
Keep in mind you should be const-correct. This means if your function doesn't modify the parameter, mark it as const. If do_something above only looked at but didn't change data, we'd mark it as const:
void do_something(const big_data& data); // alias a big_data, and don't change it
We avoid the copy and we say "hey, we won't be modifying this." This has other side effects (with things like temporary variables), but you shouldn't worry about that now.
In contrast, our swap function cannot be const, because we are indeed modifying the aliases.
Hope this clarifies some more.
*Rough pointers tutorial:
A pointer is a variable that holds the address of another variable. For example:
int i; // normal int
int* p; // points to an integer (is not an integer!)
p = &i; // &i means "address of i". p is pointing to i
*p = 2; // *p means "dereference p". that is, this goes to the int
// pointed to by p (i), and sets it to 2.
So, if you've seen the pointer-version swap function, we pass the address of the variables we want to swap, and then we do the swap, dereferencing to get and set values.
Lets take a simple example of a function named increment which increments its argument. Consider:
void increment(int input) {
input++;
}
which will not work as the change takes place on the copy of the argument passed to the function on the actual parameter. So
int i = 1;
std::cout<<i<<" ";
increment(i);
std::cout<<i<<" ";
will produce 1 1 as output.
To make the function work on the actual parameter passed we pass its reference to the function as:
void increment(int &input) { // note the &
input++;
}
the change made to input inside the function is actually being made to the actual parameter. This will produce the expected output of 1 2
GMan's answer gives you the lowdown on references. I just wanted to show you a very basic function that must use references: swap, which swaps two variables. Here it is for ints (as you requested):
// changes to a & b hold when the function exits
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
// changes to a & b are local to swap_noref and will go away when the function exits
void swap_noref(int a, int b) {
int tmp = a;
a = b;
b = tmp;
}
// changes swap_ptr makes to the variables pointed to by pa & pb
// are visible outside swap_ptr, but changes to pa and pb won't be visible
void swap_ptr(int *pa, int *pb) {
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main() {
int x = 17;
int y = 42;
// next line will print "x: 17; y: 42"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap can alter x & y
swap(x,y);
// next line will print "x: 42; y: 17"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap_noref can't alter x or y
swap_noref(x,y);
// next line will print "x: 42; y: 17"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap_ptr can alter x & y
swap_ptr(&x,&y);
// next line will print "x: 17; y: 42"
std::cout << "x: " << x << "; y: " << y << std::endl
}
There is a cleverer swap implementation for ints that doesn't need a temporary. However, here I care more about clear than clever.
Without references (or pointers), swap_noref cannot alter the variables passed to it, which means it simply cannot work. swap_ptr can alter variables, but it uses pointers, which are messy (when references won't quite cut it, however, pointers can do the job). swap is the simplest overall.
On Pointers
Pointers let you do some of the same things as references. However, pointers put more responsibility on the programmer to manage them and the memory they point to (a topic called "memory management"–but don't worry about it for now). As a consequence, references should be your preferred tool for now.
Think of variables as names bound to boxes that store a value. Constants are names bound directly to values. Both map names to values, but the value of constants can't be changed. While the value held in a box can change, the binding of name to box can't, which is why a reference cannot be changed to refer to a different variable.
Two basic operations on variables are getting the current value (done simply by using the variable's name) and assigning a new value (the assignment operator, '='). Values are stored in memory (the box holding a value is simply a contiguous region of memory). For example,
int a = 17;
results in something like (note: in the following, "foo # 0xDEADBEEF" stands for a variable with name "foo" stored at address "0xDEADBEEF". Memory addresses have been made up):
____
a # 0x1000: | 17 |
----
Everything stored in memory has a starting address, so there's one more operation: get the address of the value ("&" is the address-of operator). A pointer is a variable that stores an address.
int *pa = &a;
results in:
______ ____
pa # 0x10A0: |0x1000| ------> # 0x1000: | 17 |
------ ----
Note that a pointer simply stores a memory address, so it doesn't have access to the name of what it points to. In fact, pointers can point to things without names, but that's a topic for another day.
There are a few operations on pointers. You can dereference a pointer (the "*" operator), which gives you the data the pointer points to. Dereferencing is the opposite of getting the address: *&a is the same box as a, &*pa is the same value as pa, and *pa is the same box as a. In particular, pa in the example holds 0x1000; * pa means "the int in memory at location pa", or "the int in memory at location 0x1000". "a" is also "the int at memory location 0x1000". Other operation on pointers are addition and subtraction, but that's also a topic for another day.
// Passes in mutable references of a and b.
int doSomething(int& a, int& b) {
a = 5;
cout << "1: " << a << b; // prints 1: 5,6
}
a = 0;
b = 6;
doSomething(a, b);
cout << "2: " << a << ", " << b; // prints 2: 5,6
Alternatively,
// Passes in copied values of a and b.
int doSomething(int a, int b) {
a = 5;
cout << "1: " << a << b; // prints 1: 5,6
}
a = 0;
b = 6;
doSomething(a, b);
cout << "2: " << a << ", " << b; // prints 2: 0,6
Or the const version:
// Passes in const references a and b.
int doSomething(const int &a, const int &b) {
a = 5; // COMPILE ERROR, cannot assign to const reference.
cout << "1: " << b; // prints 1: 6
}
a = 0;
b = 6;
doSomething(a, b);
References are used to pass locations of variables, so they don't need to be copied on the stack to the new function.
A simple pair of examples which you can run online.
The first uses a normal function, and the second uses references:
Example 1 (no reference)
Example 2 (reference)
Edit - here's the source code incase you don't like links:
Example 1
using namespace std;
void foo(int y){
y=2;
}
int main(){
int x=1;
foo(x);
cout<<x;//outputs 1
}
Example 2
using namespace std;
void foo(int & y){
y=2;
}
int main(){
int x=1;
foo(x);
cout<<x;//outputs 2
}
I don't know if this is the most basic, but here goes...
typedef int Element;
typedef std::list<Element> ElementList;
// Defined elsewhere.
bool CanReadElement(void);
Element ReadSingleElement(void);
int ReadElementsIntoList(int count, ElementList& elems)
{
int elemsRead = 0;
while(elemsRead < count && CanReadElement())
elems.push_back(ReadSingleElement());
return count;
}
Here we use a reference to pass our list of elements into ReadElementsIntoList(). This way, the function loads the elements right into the list. If we didn't use a reference, then elems would be a copy of the passed-in list, which would have the elements added to it, but then elems would be discarded when the function returns.
This works both ways. In the case of count, we don't make it a reference, because we don't want to modify the count passed in, instead returning the number of elements read. This allows the calling code to compare the number of elements actually read to the requested number; if they don't match, then CanReadElement() must have returned false, and immediately trying to read some more would likely fail. If they match, then maybe count was less than the number of elements available, and a further read would be appropriate. Finally, if ReadElementsIntoList() needed to modify count internally, it could do so without mucking up the caller.
How about by metaphor: Say your function counts beans in a jar. It needs the jar of beans and you need to know the result which can't be the return value (for any number of reasons). You could send it the jar and the variable value, but you'll never know if or what it changes the value to. Instead, you need to send it that variable via a return addressed envelope, so it can put the value in that and know it's written the result to the value at said address.
Correct me if I'm wrong, but a reference is only a dereferenced pointer, or?
The difference to a pointer is, that you can't easily commit a NULL.

What is the purpose for reference parameters in c++? [duplicate]

I am trying to understand how to use reference parameters. There are several examples in my text, however they are too complicated for me to understand why and how to use them.
How and why would you want to use a reference? What would happen if you didn't make the parameter a reference, but instead left the & off?
For example, what's the difference between these functions:
int doSomething(int& a, int& b);
int doSomething(int a, int b);
I understand that reference variables are used in order to change a formal->reference, which then allows a two-way exchange of parameters. However, that is the extent of my knowledge, and a more concrete example would be of much help.
Think of a reference as an alias. When you invoke something on a reference, you're really invoking it on the object to which the reference refers.
int i;
int& j = i; // j is an alias to i
j = 5; // same as i = 5
When it comes to functions, consider:
void foo(int i)
{
i = 5;
}
Above, int i is a value and the argument passed is passed by value. That means if we say:
int x = 2;
foo(x);
i will be a copy of x. Thus setting i to 5 has no effect on x, because it's the copy of x being changed. However, if we make i a reference:
void foo(int& i) // i is an alias for a variable
{
i = 5;
}
Then saying foo(x) no longer makes a copy of x; i is x. So if we say foo(x), inside the function i = 5; is exactly the same as x = 5;, and x changes.
Hopefully that clarifies a bit.
Why is this important? When you program, you never want to copy and paste code. You want to make a function that does one task and it does it well. Whenever that task needs to be performed, you use that function.
So let's say we want to swap two variables. That looks something like this:
int x, y;
// swap:
int temp = x; // store the value of x
x = y; // make x equal to y
y = temp; // make y equal to the old value of x
Okay, great. We want to make this a function, because: swap(x, y); is much easier to read. So, let's try this:
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
This won't work! The problem is that this is swapping copies of two variables. That is:
int a, b;
swap(a, b); // hm, x and y are copies of a and b...a and b remain unchanged
In C, where references do not exist, the solution was to pass the address of these variables; that is, use pointers*:
void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int a, b;
swap(&a, &b);
This works well. However, it's a bit clumsy to use, and actually a bit unsafe. swap(nullptr, nullptr), swaps two nothings and dereferences null pointers...undefined behavior! Fixable with some checks:
void swap(int* x, int* y)
{
if (x == nullptr || y == nullptr)
return; // one is null; this is a meaningless operation
int temp = *x;
*x = *y;
*y = temp;
}
But looks how clumsy our code has gotten. C++ introduces references to solve this problem. If we can just alias a variable, we get the code we were looking for:
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
int a, b;
swap(a, b); // inside, x and y are really a and b
Both easy to use, and safe. (We can't accidentally pass in a null, there are no null references.) This works because the swap happening inside the function is really happening on the variables being aliased outside the function.
(Note, never write a swap function. :) One already exists in the header <algorithm>, and it's templated to work with any type.)
Another use is to remove that copy that happens when you call a function. Consider we have a data type that's very big. Copying this object takes a lot of time, and we'd like to avoid that:
struct big_data
{ char data[9999999]; }; // big!
void do_something(big_data data);
big_data d;
do_something(d); // ouch, making a copy of all that data :<
However, all we really need is an alias to the variable, so let's indicate that. (Again, back in C we'd pass the address of our big data type, solving the copying problem but introducing clumsiness.):
void do_something(big_data& data);
big_data d;
do_something(d); // no copies at all! data aliases d within the function
This is why you'll hear it said you should pass things by reference all the time, unless they are primitive types. (Because internally passing an alias is probably done with a pointer, like in C. For small objects it's just faster to make the copy then worry about pointers.)
Keep in mind you should be const-correct. This means if your function doesn't modify the parameter, mark it as const. If do_something above only looked at but didn't change data, we'd mark it as const:
void do_something(const big_data& data); // alias a big_data, and don't change it
We avoid the copy and we say "hey, we won't be modifying this." This has other side effects (with things like temporary variables), but you shouldn't worry about that now.
In contrast, our swap function cannot be const, because we are indeed modifying the aliases.
Hope this clarifies some more.
*Rough pointers tutorial:
A pointer is a variable that holds the address of another variable. For example:
int i; // normal int
int* p; // points to an integer (is not an integer!)
p = &i; // &i means "address of i". p is pointing to i
*p = 2; // *p means "dereference p". that is, this goes to the int
// pointed to by p (i), and sets it to 2.
So, if you've seen the pointer-version swap function, we pass the address of the variables we want to swap, and then we do the swap, dereferencing to get and set values.
Lets take a simple example of a function named increment which increments its argument. Consider:
void increment(int input) {
input++;
}
which will not work as the change takes place on the copy of the argument passed to the function on the actual parameter. So
int i = 1;
std::cout<<i<<" ";
increment(i);
std::cout<<i<<" ";
will produce 1 1 as output.
To make the function work on the actual parameter passed we pass its reference to the function as:
void increment(int &input) { // note the &
input++;
}
the change made to input inside the function is actually being made to the actual parameter. This will produce the expected output of 1 2
GMan's answer gives you the lowdown on references. I just wanted to show you a very basic function that must use references: swap, which swaps two variables. Here it is for ints (as you requested):
// changes to a & b hold when the function exits
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
// changes to a & b are local to swap_noref and will go away when the function exits
void swap_noref(int a, int b) {
int tmp = a;
a = b;
b = tmp;
}
// changes swap_ptr makes to the variables pointed to by pa & pb
// are visible outside swap_ptr, but changes to pa and pb won't be visible
void swap_ptr(int *pa, int *pb) {
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main() {
int x = 17;
int y = 42;
// next line will print "x: 17; y: 42"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap can alter x & y
swap(x,y);
// next line will print "x: 42; y: 17"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap_noref can't alter x or y
swap_noref(x,y);
// next line will print "x: 42; y: 17"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap_ptr can alter x & y
swap_ptr(&x,&y);
// next line will print "x: 17; y: 42"
std::cout << "x: " << x << "; y: " << y << std::endl
}
There is a cleverer swap implementation for ints that doesn't need a temporary. However, here I care more about clear than clever.
Without references (or pointers), swap_noref cannot alter the variables passed to it, which means it simply cannot work. swap_ptr can alter variables, but it uses pointers, which are messy (when references won't quite cut it, however, pointers can do the job). swap is the simplest overall.
On Pointers
Pointers let you do some of the same things as references. However, pointers put more responsibility on the programmer to manage them and the memory they point to (a topic called "memory management"–but don't worry about it for now). As a consequence, references should be your preferred tool for now.
Think of variables as names bound to boxes that store a value. Constants are names bound directly to values. Both map names to values, but the value of constants can't be changed. While the value held in a box can change, the binding of name to box can't, which is why a reference cannot be changed to refer to a different variable.
Two basic operations on variables are getting the current value (done simply by using the variable's name) and assigning a new value (the assignment operator, '='). Values are stored in memory (the box holding a value is simply a contiguous region of memory). For example,
int a = 17;
results in something like (note: in the following, "foo # 0xDEADBEEF" stands for a variable with name "foo" stored at address "0xDEADBEEF". Memory addresses have been made up):
____
a # 0x1000: | 17 |
----
Everything stored in memory has a starting address, so there's one more operation: get the address of the value ("&" is the address-of operator). A pointer is a variable that stores an address.
int *pa = &a;
results in:
______ ____
pa # 0x10A0: |0x1000| ------> # 0x1000: | 17 |
------ ----
Note that a pointer simply stores a memory address, so it doesn't have access to the name of what it points to. In fact, pointers can point to things without names, but that's a topic for another day.
There are a few operations on pointers. You can dereference a pointer (the "*" operator), which gives you the data the pointer points to. Dereferencing is the opposite of getting the address: *&a is the same box as a, &*pa is the same value as pa, and *pa is the same box as a. In particular, pa in the example holds 0x1000; * pa means "the int in memory at location pa", or "the int in memory at location 0x1000". "a" is also "the int at memory location 0x1000". Other operation on pointers are addition and subtraction, but that's also a topic for another day.
// Passes in mutable references of a and b.
int doSomething(int& a, int& b) {
a = 5;
cout << "1: " << a << b; // prints 1: 5,6
}
a = 0;
b = 6;
doSomething(a, b);
cout << "2: " << a << ", " << b; // prints 2: 5,6
Alternatively,
// Passes in copied values of a and b.
int doSomething(int a, int b) {
a = 5;
cout << "1: " << a << b; // prints 1: 5,6
}
a = 0;
b = 6;
doSomething(a, b);
cout << "2: " << a << ", " << b; // prints 2: 0,6
Or the const version:
// Passes in const references a and b.
int doSomething(const int &a, const int &b) {
a = 5; // COMPILE ERROR, cannot assign to const reference.
cout << "1: " << b; // prints 1: 6
}
a = 0;
b = 6;
doSomething(a, b);
References are used to pass locations of variables, so they don't need to be copied on the stack to the new function.
A simple pair of examples which you can run online.
The first uses a normal function, and the second uses references:
Example 1 (no reference)
Example 2 (reference)
Edit - here's the source code incase you don't like links:
Example 1
using namespace std;
void foo(int y){
y=2;
}
int main(){
int x=1;
foo(x);
cout<<x;//outputs 1
}
Example 2
using namespace std;
void foo(int & y){
y=2;
}
int main(){
int x=1;
foo(x);
cout<<x;//outputs 2
}
I don't know if this is the most basic, but here goes...
typedef int Element;
typedef std::list<Element> ElementList;
// Defined elsewhere.
bool CanReadElement(void);
Element ReadSingleElement(void);
int ReadElementsIntoList(int count, ElementList& elems)
{
int elemsRead = 0;
while(elemsRead < count && CanReadElement())
elems.push_back(ReadSingleElement());
return count;
}
Here we use a reference to pass our list of elements into ReadElementsIntoList(). This way, the function loads the elements right into the list. If we didn't use a reference, then elems would be a copy of the passed-in list, which would have the elements added to it, but then elems would be discarded when the function returns.
This works both ways. In the case of count, we don't make it a reference, because we don't want to modify the count passed in, instead returning the number of elements read. This allows the calling code to compare the number of elements actually read to the requested number; if they don't match, then CanReadElement() must have returned false, and immediately trying to read some more would likely fail. If they match, then maybe count was less than the number of elements available, and a further read would be appropriate. Finally, if ReadElementsIntoList() needed to modify count internally, it could do so without mucking up the caller.
How about by metaphor: Say your function counts beans in a jar. It needs the jar of beans and you need to know the result which can't be the return value (for any number of reasons). You could send it the jar and the variable value, but you'll never know if or what it changes the value to. Instead, you need to send it that variable via a return addressed envelope, so it can put the value in that and know it's written the result to the value at said address.
Correct me if I'm wrong, but a reference is only a dereferenced pointer, or?
The difference to a pointer is, that you can't easily commit a NULL.

What does it mean to have a function pointer type?

I have a class assignment that says:
Write a declaration for a function that takes two int parameters and returns an int, and declare a vector whose elements have this function pointer type.
Since the function and vector are both int is this correct? I'm really fuzzy on pointers still. This is what I have:
#include <iostream>
#include <vector>
using std::cin; using std::cout; using std::endl; using std::vector;
// This is my function that take two ints and returns and int
int AddFunc ( int a, int b) { int addResult; addResult = a + b; return (addResult);}
int main()
{
vector <int> v1; // Declare a vector whose elements have this functions pointer types
int add1, add2, add3 = 0;
cout << "Enter two numbers to be added with my AddFunc function: ";
cin >> add1 >> add2;
add3 = AddFunc (add1, add2);
cout << "The numbers added equal: " << add3 << endl;
v1.push_back(add3);
cout << "The first element in the vector v1 is: " << v1 [0] << endl;
return 0;
}
The function pointer type is int (*)(int, int). You want this:
typedef int (*fptr)(int, int);
std::vector<fptr> v;
Example:
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
v.push_back(&add);
v.push_back(&mul);
And then something like this:
for (f : v) { std::cout << "f(5, 7) = " << f(5, 7) << std::endl; }
In C++ you have the abilty to define a function pointer, like so:
int (*pfunc) (int, int);
This is a variable, to which you can assign the address of a function, as long as it has the specified signature, like so:
pfunc = AddFunc; // Assign the adress of a function
pfunc(1,2) // Now call the function through the pointer
Now, note that pfunc is the variable name, and its "official" type is int (*) (int,int)
Naturally, this can all get very confusing, so you'd probably wanna typedef it:
typedef int (*AdderFunc)(int, int);
AdderFunc pfunc = AddFunc;
pfunc(1,2);
The assignment wants a vector of function pointers for your function. Function pointers are a bit difficult to read if you're not used to them. Here's a method you can use to write a function pointer type.
First, write the argument list of the function. AddFunc() takes two int arguments, so at first you have:
(int, int)
For this to be a function pointer, you prefix it with (*):
(*)(int, int)
Lastly, you prefix the whole thing with the return type of the function. In this case, int:
int (*)(int, int)
You can use that as-is as the type of your vector:
std::vector<int (*)(int, int)> v;
This will work. However, it's usually more clear to actually define your own type for the function pointer (using typedef). At first, it seems tricky to do so, but it's easy. You already wrote down the type using the above method. The only thing that's missing is to give it a name. You do that by writing the name after the * in (*). For example (*func_ptr), so you have:
int (*func_ptr)(int, int)
And that's all you need for a typedef:
typedef int (*func_ptr)(int, int);
Now whenever you need that particular function pointer type, instead of:
int (*)(int, int)
you can write:
func_ptr
instead. So your vector declaration becomes:
std::vector<func_ptr> v;
As far as vector is concerned, func_ptr is a pointer type just like any other.
Function pointers differ from "regular" pointers in that "dereferencing" them means calling the function they point to. You don't actually dereference a function pointer. Instead, you use the () operator on them. Doing that calls the function they point to.
Assigning to a function pointer means assigning it the address of a function. For example, if you have a variable of type func_ptr (which you typedefed above):
func_ptr AddFunc_p;
You can assign it the address of AddFunc() with:
AddFunc_p = AddFunc;
Note the missing parentheses in AddFunc. You only write the name of the function, since you don't want to actually call that function, but rather want its address so you can assign it to AddFunc_p. Now you can call AddFunc() through AddFunc_p with:
AddFunc_p(some_int, another_int);
You should now be able to deduct how to put function pointers in a vector and how to apply the () operator on its elements. It will help to keep in mind that the vector simply contains elements of type func_ptr.

Understanding Pointer-to-Member operators

I copied this program from a c++ practice book. What's going on behind the scenes?
The expected output is:
sum=30 sum=70
#include<iostream>
using namespace std;
class M
{
int x;
int y;
public:
void set_xy(int a, int b)
{
x=a;
y=b;
}
friend int sum(M m);
};
int sum (M m);
//so far so good, problem begins from here. what's happening after here?
{
int M ::*px = &M ::x;
int M ::*py = &M ::y;
M *pm =&m;
int s= m.*px+ pm->*py;
return s;
}
int main()
{
M n;
void (M :: *pf)(int, int) = &M ::set_xy;
(n.*pf)(10, 20);
cout <<"sum=" << sum(n) << endl;
M *op= &n;
(op-> *pf)(30,40);
cout << "sum=" << sum(n)<< endl;
cin.ignore();
getchar();
return 0;
}
The problem is because of extra whitespace at op-> *pf:
(op->*pf)(30,40); // ok
I think #fefe has probably said the reason in comment. ->* is a single operator, similar to .*. So, if those 2 are separated, then it will result in different syntax, which gives compiler error.
Take a look at Pointer to class data. And for the error, ->* is an operator, you can't put a space between them.
iammilind bet me to the error; op-> *pf must be changed so that you have ->* together as a single operator - a pointer to member operator (couldn't find a better link). The whitespace in op ->* pf is perfectly valid.
That's the same for something like i++; ++ is a single operator and will cause an error if you try and have i+ +.
Now for what it's doing. The example is of a pointer to a member function. pf is being declared as a member function of class M, that takes two int arguments with a void return type. It's being initialized to point to the M::set_xy function.
Inside main:
n is of type M, therefore in order to use pf to call set_xy of n you'd use the .* operator: (n.*pf)(10, 20);. That's equivalent to n.set_xy(10, 20);.
Since op is of type M* (a pointer to an M object), you'll need to use the ->* operator and call the function pointed to by pf as: (op->*pf)(30, 40);, which is equivalent to op->set_xy(30, 40);
Inside sum:
The examples are simply of pointers to member/instance variables, as opposed to member functions. It's simply demonstrating how you would add together m.x and m.y using those types of pointers.

How do I use Reference Parameters in C++?

I am trying to understand how to use reference parameters. There are several examples in my text, however they are too complicated for me to understand why and how to use them.
How and why would you want to use a reference? What would happen if you didn't make the parameter a reference, but instead left the & off?
For example, what's the difference between these functions:
int doSomething(int& a, int& b);
int doSomething(int a, int b);
I understand that reference variables are used in order to change a formal->reference, which then allows a two-way exchange of parameters. However, that is the extent of my knowledge, and a more concrete example would be of much help.
Think of a reference as an alias. When you invoke something on a reference, you're really invoking it on the object to which the reference refers.
int i;
int& j = i; // j is an alias to i
j = 5; // same as i = 5
When it comes to functions, consider:
void foo(int i)
{
i = 5;
}
Above, int i is a value and the argument passed is passed by value. That means if we say:
int x = 2;
foo(x);
i will be a copy of x. Thus setting i to 5 has no effect on x, because it's the copy of x being changed. However, if we make i a reference:
void foo(int& i) // i is an alias for a variable
{
i = 5;
}
Then saying foo(x) no longer makes a copy of x; i is x. So if we say foo(x), inside the function i = 5; is exactly the same as x = 5;, and x changes.
Hopefully that clarifies a bit.
Why is this important? When you program, you never want to copy and paste code. You want to make a function that does one task and it does it well. Whenever that task needs to be performed, you use that function.
So let's say we want to swap two variables. That looks something like this:
int x, y;
// swap:
int temp = x; // store the value of x
x = y; // make x equal to y
y = temp; // make y equal to the old value of x
Okay, great. We want to make this a function, because: swap(x, y); is much easier to read. So, let's try this:
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
This won't work! The problem is that this is swapping copies of two variables. That is:
int a, b;
swap(a, b); // hm, x and y are copies of a and b...a and b remain unchanged
In C, where references do not exist, the solution was to pass the address of these variables; that is, use pointers*:
void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int a, b;
swap(&a, &b);
This works well. However, it's a bit clumsy to use, and actually a bit unsafe. swap(nullptr, nullptr), swaps two nothings and dereferences null pointers...undefined behavior! Fixable with some checks:
void swap(int* x, int* y)
{
if (x == nullptr || y == nullptr)
return; // one is null; this is a meaningless operation
int temp = *x;
*x = *y;
*y = temp;
}
But looks how clumsy our code has gotten. C++ introduces references to solve this problem. If we can just alias a variable, we get the code we were looking for:
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
int a, b;
swap(a, b); // inside, x and y are really a and b
Both easy to use, and safe. (We can't accidentally pass in a null, there are no null references.) This works because the swap happening inside the function is really happening on the variables being aliased outside the function.
(Note, never write a swap function. :) One already exists in the header <algorithm>, and it's templated to work with any type.)
Another use is to remove that copy that happens when you call a function. Consider we have a data type that's very big. Copying this object takes a lot of time, and we'd like to avoid that:
struct big_data
{ char data[9999999]; }; // big!
void do_something(big_data data);
big_data d;
do_something(d); // ouch, making a copy of all that data :<
However, all we really need is an alias to the variable, so let's indicate that. (Again, back in C we'd pass the address of our big data type, solving the copying problem but introducing clumsiness.):
void do_something(big_data& data);
big_data d;
do_something(d); // no copies at all! data aliases d within the function
This is why you'll hear it said you should pass things by reference all the time, unless they are primitive types. (Because internally passing an alias is probably done with a pointer, like in C. For small objects it's just faster to make the copy then worry about pointers.)
Keep in mind you should be const-correct. This means if your function doesn't modify the parameter, mark it as const. If do_something above only looked at but didn't change data, we'd mark it as const:
void do_something(const big_data& data); // alias a big_data, and don't change it
We avoid the copy and we say "hey, we won't be modifying this." This has other side effects (with things like temporary variables), but you shouldn't worry about that now.
In contrast, our swap function cannot be const, because we are indeed modifying the aliases.
Hope this clarifies some more.
*Rough pointers tutorial:
A pointer is a variable that holds the address of another variable. For example:
int i; // normal int
int* p; // points to an integer (is not an integer!)
p = &i; // &i means "address of i". p is pointing to i
*p = 2; // *p means "dereference p". that is, this goes to the int
// pointed to by p (i), and sets it to 2.
So, if you've seen the pointer-version swap function, we pass the address of the variables we want to swap, and then we do the swap, dereferencing to get and set values.
Lets take a simple example of a function named increment which increments its argument. Consider:
void increment(int input) {
input++;
}
which will not work as the change takes place on the copy of the argument passed to the function on the actual parameter. So
int i = 1;
std::cout<<i<<" ";
increment(i);
std::cout<<i<<" ";
will produce 1 1 as output.
To make the function work on the actual parameter passed we pass its reference to the function as:
void increment(int &input) { // note the &
input++;
}
the change made to input inside the function is actually being made to the actual parameter. This will produce the expected output of 1 2
GMan's answer gives you the lowdown on references. I just wanted to show you a very basic function that must use references: swap, which swaps two variables. Here it is for ints (as you requested):
// changes to a & b hold when the function exits
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
// changes to a & b are local to swap_noref and will go away when the function exits
void swap_noref(int a, int b) {
int tmp = a;
a = b;
b = tmp;
}
// changes swap_ptr makes to the variables pointed to by pa & pb
// are visible outside swap_ptr, but changes to pa and pb won't be visible
void swap_ptr(int *pa, int *pb) {
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main() {
int x = 17;
int y = 42;
// next line will print "x: 17; y: 42"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap can alter x & y
swap(x,y);
// next line will print "x: 42; y: 17"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap_noref can't alter x or y
swap_noref(x,y);
// next line will print "x: 42; y: 17"
std::cout << "x: " << x << "; y: " << y << std::endl
// swap_ptr can alter x & y
swap_ptr(&x,&y);
// next line will print "x: 17; y: 42"
std::cout << "x: " << x << "; y: " << y << std::endl
}
There is a cleverer swap implementation for ints that doesn't need a temporary. However, here I care more about clear than clever.
Without references (or pointers), swap_noref cannot alter the variables passed to it, which means it simply cannot work. swap_ptr can alter variables, but it uses pointers, which are messy (when references won't quite cut it, however, pointers can do the job). swap is the simplest overall.
On Pointers
Pointers let you do some of the same things as references. However, pointers put more responsibility on the programmer to manage them and the memory they point to (a topic called "memory management"–but don't worry about it for now). As a consequence, references should be your preferred tool for now.
Think of variables as names bound to boxes that store a value. Constants are names bound directly to values. Both map names to values, but the value of constants can't be changed. While the value held in a box can change, the binding of name to box can't, which is why a reference cannot be changed to refer to a different variable.
Two basic operations on variables are getting the current value (done simply by using the variable's name) and assigning a new value (the assignment operator, '='). Values are stored in memory (the box holding a value is simply a contiguous region of memory). For example,
int a = 17;
results in something like (note: in the following, "foo # 0xDEADBEEF" stands for a variable with name "foo" stored at address "0xDEADBEEF". Memory addresses have been made up):
____
a # 0x1000: | 17 |
----
Everything stored in memory has a starting address, so there's one more operation: get the address of the value ("&" is the address-of operator). A pointer is a variable that stores an address.
int *pa = &a;
results in:
______ ____
pa # 0x10A0: |0x1000| ------> # 0x1000: | 17 |
------ ----
Note that a pointer simply stores a memory address, so it doesn't have access to the name of what it points to. In fact, pointers can point to things without names, but that's a topic for another day.
There are a few operations on pointers. You can dereference a pointer (the "*" operator), which gives you the data the pointer points to. Dereferencing is the opposite of getting the address: *&a is the same box as a, &*pa is the same value as pa, and *pa is the same box as a. In particular, pa in the example holds 0x1000; * pa means "the int in memory at location pa", or "the int in memory at location 0x1000". "a" is also "the int at memory location 0x1000". Other operation on pointers are addition and subtraction, but that's also a topic for another day.
// Passes in mutable references of a and b.
int doSomething(int& a, int& b) {
a = 5;
cout << "1: " << a << b; // prints 1: 5,6
}
a = 0;
b = 6;
doSomething(a, b);
cout << "2: " << a << ", " << b; // prints 2: 5,6
Alternatively,
// Passes in copied values of a and b.
int doSomething(int a, int b) {
a = 5;
cout << "1: " << a << b; // prints 1: 5,6
}
a = 0;
b = 6;
doSomething(a, b);
cout << "2: " << a << ", " << b; // prints 2: 0,6
Or the const version:
// Passes in const references a and b.
int doSomething(const int &a, const int &b) {
a = 5; // COMPILE ERROR, cannot assign to const reference.
cout << "1: " << b; // prints 1: 6
}
a = 0;
b = 6;
doSomething(a, b);
References are used to pass locations of variables, so they don't need to be copied on the stack to the new function.
A simple pair of examples which you can run online.
The first uses a normal function, and the second uses references:
Example 1 (no reference)
Example 2 (reference)
Edit - here's the source code incase you don't like links:
Example 1
using namespace std;
void foo(int y){
y=2;
}
int main(){
int x=1;
foo(x);
cout<<x;//outputs 1
}
Example 2
using namespace std;
void foo(int & y){
y=2;
}
int main(){
int x=1;
foo(x);
cout<<x;//outputs 2
}
I don't know if this is the most basic, but here goes...
typedef int Element;
typedef std::list<Element> ElementList;
// Defined elsewhere.
bool CanReadElement(void);
Element ReadSingleElement(void);
int ReadElementsIntoList(int count, ElementList& elems)
{
int elemsRead = 0;
while(elemsRead < count && CanReadElement())
elems.push_back(ReadSingleElement());
return count;
}
Here we use a reference to pass our list of elements into ReadElementsIntoList(). This way, the function loads the elements right into the list. If we didn't use a reference, then elems would be a copy of the passed-in list, which would have the elements added to it, but then elems would be discarded when the function returns.
This works both ways. In the case of count, we don't make it a reference, because we don't want to modify the count passed in, instead returning the number of elements read. This allows the calling code to compare the number of elements actually read to the requested number; if they don't match, then CanReadElement() must have returned false, and immediately trying to read some more would likely fail. If they match, then maybe count was less than the number of elements available, and a further read would be appropriate. Finally, if ReadElementsIntoList() needed to modify count internally, it could do so without mucking up the caller.
How about by metaphor: Say your function counts beans in a jar. It needs the jar of beans and you need to know the result which can't be the return value (for any number of reasons). You could send it the jar and the variable value, but you'll never know if or what it changes the value to. Instead, you need to send it that variable via a return addressed envelope, so it can put the value in that and know it's written the result to the value at said address.
Correct me if I'm wrong, but a reference is only a dereferenced pointer, or?
The difference to a pointer is, that you can't easily commit a NULL.