Related
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.
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.
In the following code
#include<iostream>
using namespace std;
int main(){
int x=4;
int y=5;
cout << x <<endl;
int& foo = x;
// foo is now a reference to x so this sets x to 56
foo = 56; //reseting the reference foo
cout << x <<endl;
cout << foo <<endl;
foo= y; //this is supposed to be forbidden
cout << foo <<endl; // but I am getting foo=5
return 1;
}
This is compiling fine and I get foo=5 in the last cout. For what I've read you cannot reseat a reference to make it refer to a different object, so I was expecting an error, what is going here?
Once a reference has been created, any attempt to use the reference variable is equivalent to using the object that was assigned to it.
So when we look at the following line of code:
foo= y; //this is suppose to be forbidden
We see that it does not attempt to re-assign the reference, it assigns the value of y to the object referred to by foo.
What would be an example of reseting a reference (that would generate an error), then?
While we can't write code that reassigns references, the compiler can end up in situations where it would have to emit code that is the equivalent of that when dealing with references embedded within other data structures. And it's still illegal for the compiler to do so.
For example, the following will fail to compile because the compiler-generated assignement operator for X cannot be created since it would involve reassigning ref.
struct X {
int& ref;
};
void foo() {
int v1 = 1;
int v2 = 2;
X x1{v1};
X x2{v2};
x1 = x2; // Boom!
}
Edit: Answering the followup question here because it's extremely relevant.
Now you may wonder: "Hey! if the reference behaves as a proxy for another variable, why can't the compiler just use that logic to generate a valid assignment operator for struct X?"
Well, not really. The underlying expectation here is that once i do var_a = var_b, then by default, var_a is now effectively the same as var_b.
So if x1.ref points to v1 and x2.ref points to v2, then the expectation is that by default, x1 = x2 would lead to x1.ref pointing to v2.
Doing anything else would just lead to confusion and surprises in the long run.
I am a beginner in C++ and want to do simple example of composite function.
For example, in MATLAB, I can write
a = #(x) 2*x
b = #(y) 3*y
a(b(1))
Answer is 6
I searched following questions.
function composition in C++ / C++11 and
Function Composition in C++
But they are created using advanced features, such as templates, to which I am not much familiar at this time. Is there a simple and more direct way to achieve this? In above MATLAB code, user does not need to know implementation of function handles. User can just use proper syntax to get result. Is there such way in C++?
** Another Edit:**
In above code, I am putting a value at the end. However, if I want to pass the result to a third function, MATLAB can still consider it as a function. But, how to do this in C++?
For example, in addition to above code, consider this code:
c = #(p,q) a(p)* b(q) %This results a function
c(1,2)
answer=12
d = #(r) a(b(r))
d(1)
answer=6
function [ output1 ] = f1( arg1 )
val = 2.0;
output1 = feval(arg1,val)
end
f1(d)
answer = 12
In this code, c takes two functions as input and d is composite function. In the next example, function f1 takes a function as argument and use MATLAB builtin function feval to evaluate the function at val.
How can I achieve this in C++?
How about:
#include <iostream>
int main(int, char**)
{
auto a = [](int x) { return 2 * x; };
auto b = [](int y) { return 3 * y; };
for (int i = 0; i < 5; ++i)
std::cout << i << " -> " << a(b(i)) << std::endl;
return 0;
}
Perhaps I'm misunderstanding your question, but it sounds easy:
int a(const int x) { return x * 2; }
int b(const int y) { return y * 3; }
std::cout << a(b(1)) << std::endl;
Regarding your latest edit, you can make a function return a result of another function:
int fun1(const int c) { return a(c); }
std::cout << fun1(1) << std::endl;
Note that this returns a number, the result of calling a, not the function a itself. Sure, you can return a pointer to that function, but then the syntax would be different: you'd have to write something like fun1()(1), which is rather ugly and complicated.
C++'s evaluation strategy for function arguments is always "eager" and usually "by value". The short version of what that means is, a composed function call sequence such as
x = a(b(c(1)));
is exactly the same as
{
auto t0 = c(1);
auto t1 = b(t0);
x = a(t1);
}
(auto t0 means "give t0 whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0 and t1 are destroyed after the assignment to x.)
I bring this up because you keep talking about functions "taking functions as input". There are programming languages, such as R, where writing a(b(1)) would pass the expression b(1) to a, and only actually call b when a asked for the expression to be evaluated. I thought MATLAB was not like that, but I could be wrong. Regardless, C++ is definitely not like that. In C++, a(b(1)) first evaluates b(1) and then passes the result of that evaluation to a; a has no way of finding out that the result came from a call to b. The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval.
Now: The most direct translation of the MATLAB code you've shown is
#include <stdio.h>
static double a(double x) { return 2*x; }
static double b(double y) { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r) { return a(b(r)); }
static double f1(double (*arg1)(double))
{ return arg1(2.0); }
int main()
{
printf("%g\n", a(b(1))); // prints 6
printf("%g\n", c(1,2)); // prints 12
printf("%g\n", d(1)); // prints 6
printf("%g\n", f1(d)); // prints 12
printf("%g\n", f1(a)); // prints 4
return 0;
}
(C++ has no need for explicit syntax like feval, because the typed parameter declaration, double (*arg1)(double) tells the compiler that arg1(2.0) is valid. In older code you may see (*arg1)(2.0) but that's not required, and I think it makes the code less readable.)
(I have used printf in this code, instead of C++'s iostreams, partly because I personally think printf is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.)
There are significant differences; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; if I'd wanted b to call c I would have had to swap them or write a "forward declaration" of c above b; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. Stick to free functions with fixed type signatures at first.
Finally, I would be remiss if I didn't mention that in
static double c(double p, double q) { return a(p) * b(q); }
the calls to a and b might happen in either order. There is talk of changing this but it has not happened yet.
int a(const int x){return x * 2;}
int b(const int x){return x * 3;}
int fun1(const int x){return a(x);}
std::cout << fun1(1) << std::endl; //returns 2
This is basic compile-time composition. If you wanted runtime composition, things get a tad more involved.
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.