I am totally new to c++ and thought it would be good practice to write a program which solved a given liter puzzle (you have 2 containers with capacities of 3 and 5 liters, can you obtain 4 liters? etc.)
I wrote a class for a given container and a function which was intended to 'pour' the contents of one container into another. The function doesn't change the value of the contents of any object however, despite the entire class being public. I'm not sure what I'm doing wrong.
Here is my code:
#include <iostream>
using namespace std;
class Container {
public:
int quantity; //quantity of water in container
int size; //max amt of water
};
void pour(Container a, Container b) {
int differential = b.size - b.quantity;
if (a.quantity <= differential) {
b.quantity = a.quantity + b.quantity;
a.quantity = 0;
}
else if (a.quantity > differential) {
b.quantity = b.quantity - differential;
a.quantity = a.quantity - differential;
}
};
int main() {
Container bottle1;
bottle1.quantity = 5;
bottle1.size = 6;
Container bottle2;
bottle2.quantity = 0;
bottle2.size = 2;
pour(bottle2, bottle1);
cout << bottle1.quantity << ", " << bottle2.quantity << endl;
return 0;
}
I'm sure my mistake is obvious but I can't find an answer anywhere. Any help would be greatly appreciated.
You're passing the Container
s as copies. This means that the containers you alter in the pour
function are destructed upon function exit.
The solution is to use references:
void pour(Container& a, Container& b)
The &
after the type denotes a reference. This means that, instead of copies of a
and b
being used inside pour
, the function gets access to the same a
and b
as the caller.
This is probably because you're passing the objects by value. You'll want to pass them by reference. You can do this by changing your method header.
Essentially, each instance of Container
in the method header should become Container&
. The call will not need to be changed.
You can also pass pointers. Your arguments would then become Container *a
, and in your call you'd have to add an ampersand (&
) before each variable name (e.g. a
becomes &a
). You'd then also have to change any derefs of the object from periods (.
) to arrows (->
).
Your method would become:
void pour(Container *a, Container *b) {
int differential = b->size - b->quantity;
if (a->quantity <= differential) {
b->quantity = a->quantity + b->quantity;
a->quantity = 0;
}
else if (a->quantity > differential) {
b->quantity = b->quantity - differential;
a->quantity = a->quantity - differential;
}
};
I mentioned both because in some cases, the designers of a program will adopt the convention that all references are const references. That is, any object passed by reference is not to be modified (which is enforced by using the const
keyword before the type name in a method header), and that all other objects are passed by pointer. This makes it more clear, in the function call, whether or not an argument will be modified.
The choice of using a const reference over pass-by-value in that convention is to improve the efficiency of a function call. It is quicker to pass a reference than to make a copy of an object.