I am confused on how the code below can be sent a variable and then change that variable to the value at the top of the stack without "returning" a value. So if 1 was at the top I could do stack.pop(variable) and then variable would equal 1.
void DynIntStack::pop(int &num)
{
StackNode *temp; // Temporary pointer
// First make sure the stack isn't empty.
if (isEmpty())
{
cout << "The stack is empty.\n";
}
else // pop value off top of stack
{
num = top->value;
temp = top->next;
delete top;
top = temp;
}
}
This is a parameter passed by reference.
You can think of it as passing the actual parameter, not just the value. Any modification done to the parameter is reflected to the original variable just because they are the same variable.
Actually the parameter is a reference (pointer) to the memory address of the real value.
When you call a function that takes a reference, such as
void setNum(int &num) {
num = 4;
}
main(...) {
int myNum = 2;
setNum(myNum);
cout << myNum << endl;
}
you're telling the compiler to pass the argument's address, rather than its value. When you assign a value to the reference, it changes the memory at that address. Then, when the function returns, the original variable still points at the same address, so it assumes the new value.
On the other hand, when you declare a function that takes a value, such as
void leaveNumUnchanged(int num) {
num++;
cout << "The new value is " << num << endl;
}
the function makes its own private copy of the argument, and any manipulations affect only the copy.
Related
Under which circumstances would you want to use code of this nature in c++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.
This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.
50% of C++ programmers like to set their pointers to null after a delete:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
Without the reference, you would only be changing a local copy of the pointer, not affecting the caller.
David's answer is correct, but if it's still a little abstract, here are two examples:
You might want to zero all freed pointers to catch memory problems earlier. C-style you'd do:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
In C++ to do the same, you might do:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
When dealing with linked-lists - often simply represented as pointers to a next node:
struct Node
{
value_t value;
Node* next;
};
In this case, when you insert to the empty list you necessarily must change the incoming pointer because the result is not the NULL pointer anymore. This is a case where you modify an external pointer from a function, so it would have a reference to pointer in its signature:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
There's an example in this question.
I have had to use code like this to provide functions to allocate memory to a pointer passed in and return its size because my company "object" to me using the STL
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
It is not nice, but the pointer must be passed by reference (or use double pointer). If not, memory is allocated to a local copy of the pointer if it is passed by value which results in a memory leak.
One example is when you write a parser function and pass it a source pointer to read from, if the function is supposed to push that pointer forward behind the last character which has been correctly recognized by the parser. Using a reference to a pointer makes it clear then that the function will move the original pointer to update its position.
In general, you use references to pointers if you want to pass a pointer to a function and let it move that original pointer to some other position instead of just moving a copy of it without affecting the original.
Another situation when you may need this is if you have stl collection of pointers and want to change
them using stl algorithm. Example of for_each in c++98.
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
Otherwise, if you use changeObject(Object* item) signature you have copy of pointer, not original one.
Refer the code below:
When we pass x as Node *x, a new variable is created with the same address passed on by the caller function.
If you modify the value pointed by the pointer, that change will be reflected in the caller function variable.
But if we change the value of the pointer itself it will not be reflected in the caller function because callee function has the copy of the passed pointer not the original pointer itself.
void increment(int *x) {
(*x)++;
x++;
cout << x << endl; // prints 0x7ffe9f8e1900
}
int main() {
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints 11
cout << x << endl; // prints 0x7ffe9f8e18fc
return 0;
}
Now, check the below code:
When we pass x as Node *&x, we pass a reference of the original variable present in the caller function meaning these two variable (caller and callee root) are same, their name may differ.
if we modify the value pointer by the pointer, that change will be reflected in the caller function variable.
Now if we change the value of the pointer itself it will also be reflected in the caller function variable.
void increment(int* &x)
{
(*x) ++;
cout << *x << endl; // prints 11
x++;
cout << x << endl; // prints 0x7fffb93eba70
}
int main()
{
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints garbage
cout << x << endl; // prints 0x7fffb93eba70
return 0;
}
Under which circumstances would you want to use code of this nature in c++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.
This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.
50% of C++ programmers like to set their pointers to null after a delete:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
Without the reference, you would only be changing a local copy of the pointer, not affecting the caller.
David's answer is correct, but if it's still a little abstract, here are two examples:
You might want to zero all freed pointers to catch memory problems earlier. C-style you'd do:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
In C++ to do the same, you might do:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
When dealing with linked-lists - often simply represented as pointers to a next node:
struct Node
{
value_t value;
Node* next;
};
In this case, when you insert to the empty list you necessarily must change the incoming pointer because the result is not the NULL pointer anymore. This is a case where you modify an external pointer from a function, so it would have a reference to pointer in its signature:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
There's an example in this question.
I have had to use code like this to provide functions to allocate memory to a pointer passed in and return its size because my company "object" to me using the STL
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
It is not nice, but the pointer must be passed by reference (or use double pointer). If not, memory is allocated to a local copy of the pointer if it is passed by value which results in a memory leak.
One example is when you write a parser function and pass it a source pointer to read from, if the function is supposed to push that pointer forward behind the last character which has been correctly recognized by the parser. Using a reference to a pointer makes it clear then that the function will move the original pointer to update its position.
In general, you use references to pointers if you want to pass a pointer to a function and let it move that original pointer to some other position instead of just moving a copy of it without affecting the original.
Another situation when you may need this is if you have stl collection of pointers and want to change
them using stl algorithm. Example of for_each in c++98.
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
Otherwise, if you use changeObject(Object* item) signature you have copy of pointer, not original one.
Refer the code below:
When we pass x as Node *x, a new variable is created with the same address passed on by the caller function.
If you modify the value pointed by the pointer, that change will be reflected in the caller function variable.
But if we change the value of the pointer itself it will not be reflected in the caller function because callee function has the copy of the passed pointer not the original pointer itself.
void increment(int *x) {
(*x)++;
x++;
cout << x << endl; // prints 0x7ffe9f8e1900
}
int main() {
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints 11
cout << x << endl; // prints 0x7ffe9f8e18fc
return 0;
}
Now, check the below code:
When we pass x as Node *&x, we pass a reference of the original variable present in the caller function meaning these two variable (caller and callee root) are same, their name may differ.
if we modify the value pointer by the pointer, that change will be reflected in the caller function variable.
Now if we change the value of the pointer itself it will also be reflected in the caller function variable.
void increment(int* &x)
{
(*x) ++;
cout << *x << endl; // prints 11
x++;
cout << x << endl; // prints 0x7fffb93eba70
}
int main()
{
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints garbage
cout << x << endl; // prints 0x7fffb93eba70
return 0;
}
I've been making a tree, because planting a trees will save the planet (or just the program).
class Tree {
Node* root;
// ...
void insert(int value){
private_insert(value, root);
}
void insert_private(int value, node* n){
if(n == nullptr){
n = new node(value);
} else {
your standard recursive insertion function here
}
}
// ...
};
Long story short i've tried using shared_ptrs first, but the the insert() function will never add any element into my tree. I thought i might be doing something wrong with shareds so i tried raw pointers and i got the same non-inserty resoults.
Turns out i need to pass a reference my root/nodes.
void insert_private(int value, node*& n) {...};
I understand that if i dont pass something as reference then a copy is made. But if a pointer holds an address, doesnt it's copy hold the same address? if i make a new() to a non-referenced pointer why doesnt it stick to my root/nodes?
The why is my question here, i can accept it that it works like this, my tree works, but i dont know why its like this.
edit: After reading the comments i created this small expert level program:
void fn(int* i){
cout << "Address of local in fn before change: " << i << endl;
i = new int(2);
// so basically here we made a new int, and i will get the address of
// this integer and will point to there, what we passed on before
// becomes irrelevant
cout << "Address of local in fn after change: " << i << endl;
}
void fn2(int **i){
cout << "Address of local in fn2 before change: " << i << endl;
*i = new int(2);
cout << "Address of local in fn2 after change: " << i << endl;
}
int main(){
int* p = nullptr;
cout << "Address of p: " << p << endl;
fn(p);
cout << "p& is: " << &p << endl;
fn2(&p);
cin.get();
return 0;
};
Thank you, everyone, for the answers, it helped a lot. random.org will determine who's the one who will get the approved answer thing.
Yes it's a copy and it holds the same address, but you are assigning only to the copy which is then thrown away when the function returns. The original is unaltered. That's your problem.
As an aside, IMHO, if you are altering the value of a parameter, you should use a pointer, hence a pointer to a pointer in your case. It makes it much more obvious to the reader that you're changing the value.
n = new node(value); is an assignment.
The pointer gets a new value. Now it points to somewhere else. The pointer was passed by value, so the calling code won't see any change - the assignment only had a local effect.
In insert_node you are changing what n is pointing to.
If you want that to be reflected in the caller, then you need to pass the pointer n by reference: void insert_private(int value, node*& n), although I prefer node** n as that signals to the caller of the function that the parameter value might change.
Although, since root is a class member, you can modify it directly within insert_private.
But if a pointer holds an address, doesnt it's copy hold the same address?
Sure, until you change the address held in the copy.
Your design aside to the "why?": A pointer is a normal variable. Changes made to a local copy in the callee won't be reflected on the caller side.
void foo (int a)
{ // here: a is a copy of whatever will be passed to foo
a = 2;
}
void foo2 (int &a)
{ // here: a is something like 'a local name' for the int passed to foo2
a = 3;
}
int x = 0;
foo(x); // inside foo(x), a is another int copied from x
// x still 0 here
foo2(x); // inside foo2(x), a is 'a local name' for x
// x == 3 now
Pointers behave the same way as they're just variables containing an address.
void bar (int * a)
{
a = new int;
}
void bar2(int * &a)
{
a = new int;
}
int * x = nullptr;
bar(x); // inside bar(x), a is a new pointer copied from x
// x still nullptr here
// (and memory leaking from the new without delete)
bar2(x); // inside bar2(x), a is 'a name' for the passed pointer x
// x contains memory address from a new int
delete x;
// can be deleted -> no leak
Here's my function,
template <class KeyType >
KeyType * Stack<KeyType>::Pop(KeyType& x) {
if (IsEmpty()) { //isempty is just a bool function
StackEmpty(); //just prints out that stack is empty
return 0; //bad coding breaking out of the function
}
x = stack[top--]; //stack is a pointer to an array, top is the top of the stack
return &x;
}
My questions is:
I'm not sure how this would be called in main. To my understanding a pop function shouldn't really have an option of what to pop off of the stack. LIFO right? The main question is what exactly does the Keytype& x parameters take and how would you call it in main? (in this case the KeyType is initialized as KeyType *stack an int in this particular program).
That's a very weirdly designed function.
Stack is a class template parameterised by the type stored on the stack (named KeyType for some reason). The function takes an output parameter x of type reference to KeyType and if the stack is not empty, assigns the popped value into x. At the same time, it returns its address (it returns a pointer to KeyType). If the stack was empty when pop() was called, it will call StackEmpty() and then return a null pointer.
Usage:
int main() {
Stack<int> stack;
//fill stack somehow
int val;
stack.pop(val); //val will be set to the popped item, or unchanged if the stack was empty
// You can also use the return value to access the popped item:
std::cout << *stack.pop(val);
// ... or use it to test whether the pop() succeeeded
if (stack.pop(val)) {
//val was popped, use it
}
}
It fills the value of the popped item
int main(..)
{
...
int poppedItem;
stack.pop(poppedItem);
}
If the KeyType parameter is an int as you said, then your Stack will probably look like this:
Stack<int> stack;
The ampersand in the Pop method means that you pass in a reference of the KeyType (which is int in your case). That is, the Pop method does not only return the value of the popped item but also puts the value in the passed argument.
int a, b;
a = *(stack.pop(b));
cout << a << " = " << b << endl;
variable x is the same that return value (just other way to get top element that was excluded from stack)
Stack<int> my_stack;
// blah-blah-blah ...
int tmp;
int* tmp_pointer = my_stack.pop(tmp);
some_func(tmp);
some_other_func(*tmp_pointer);
// tmp_pointer == &tmp;
// you can use one of two ways
To my understanding the function takes any element of keytype and retrieves a reference.
so calling
int value = 0;
Pop(value);
is calling Pop with &value - so in fact with the address of the int value and therefore by reference.
I wonder about the return 0 in case you called Pop with any non numerical datatype the compiler might tell you, that the return statement is invalid. Maybe returning NULL would be better. (At least better to read)
Under which circumstances would you want to use code of this nature in c++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.
This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.
50% of C++ programmers like to set their pointers to null after a delete:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
Without the reference, you would only be changing a local copy of the pointer, not affecting the caller.
David's answer is correct, but if it's still a little abstract, here are two examples:
You might want to zero all freed pointers to catch memory problems earlier. C-style you'd do:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
In C++ to do the same, you might do:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
When dealing with linked-lists - often simply represented as pointers to a next node:
struct Node
{
value_t value;
Node* next;
};
In this case, when you insert to the empty list you necessarily must change the incoming pointer because the result is not the NULL pointer anymore. This is a case where you modify an external pointer from a function, so it would have a reference to pointer in its signature:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
There's an example in this question.
I have had to use code like this to provide functions to allocate memory to a pointer passed in and return its size because my company "object" to me using the STL
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
It is not nice, but the pointer must be passed by reference (or use double pointer). If not, memory is allocated to a local copy of the pointer if it is passed by value which results in a memory leak.
One example is when you write a parser function and pass it a source pointer to read from, if the function is supposed to push that pointer forward behind the last character which has been correctly recognized by the parser. Using a reference to a pointer makes it clear then that the function will move the original pointer to update its position.
In general, you use references to pointers if you want to pass a pointer to a function and let it move that original pointer to some other position instead of just moving a copy of it without affecting the original.
Another situation when you may need this is if you have stl collection of pointers and want to change
them using stl algorithm. Example of for_each in c++98.
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
Otherwise, if you use changeObject(Object* item) signature you have copy of pointer, not original one.
Refer the code below:
When we pass x as Node *x, a new variable is created with the same address passed on by the caller function.
If you modify the value pointed by the pointer, that change will be reflected in the caller function variable.
But if we change the value of the pointer itself it will not be reflected in the caller function because callee function has the copy of the passed pointer not the original pointer itself.
void increment(int *x) {
(*x)++;
x++;
cout << x << endl; // prints 0x7ffe9f8e1900
}
int main() {
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints 11
cout << x << endl; // prints 0x7ffe9f8e18fc
return 0;
}
Now, check the below code:
When we pass x as Node *&x, we pass a reference of the original variable present in the caller function meaning these two variable (caller and callee root) are same, their name may differ.
if we modify the value pointer by the pointer, that change will be reflected in the caller function variable.
Now if we change the value of the pointer itself it will also be reflected in the caller function variable.
void increment(int* &x)
{
(*x) ++;
cout << *x << endl; // prints 11
x++;
cout << x << endl; // prints 0x7fffb93eba70
}
int main()
{
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints garbage
cout << x << endl; // prints 0x7fffb93eba70
return 0;
}