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
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;
}
I'm new to c++ and tried to get familiar with the language by implementing a LinkedList.
class ListElement {
public:
int val;
ListElement *next;
ListElement(int v, ListElement *n) {val = v; next = n;};
};
ListElement contains an int value val and a pointer to the next list element (nullptr if there is no next element) and a constructor.
class MyLinkedList {
public:
ListElement *head;
MyLinkedList() {head = nullptr;};
ListElement* getHead(void){
return head;
};
void append(int i) {
head = &ListElement(i, head);
};
};
MyLinkedList contains a pointer to the first element of the list named head as well as some methods working on the list. Encountering some bugs in those methods I tried to track down their cause. (I'm aware that a getter for a public class member makes no sense at all, originally head was private.) Doing so I observed the following behaviour I can't explain:
int main() {
MyLinkedList l;
l.append(1);
int x = l.head->val;
cout << "head: " << x << "\n";
int y = l.getHead()->val;
cout << "getHead(): " << y << "\n";
int z = l.head->val;
cout << "head: " << z << "\n";
cin.get();
return 0;
}
Running this code (add #include <iostream> and using namespace std; for a working example) prints
head: 1
getHead(): 18085840
head: -858993460
so the first direct access of head works just as expected, yielding 1 as value of the first list element, but using the getter returns garbage. If head is then accessed directly again, it also yields garbage, which made me think "Hm, seems like using getHead() somehow garbles the ListMember object", just to discover that
int x = l.head->val;
cout << "head: " << x << "\n";
int z = l.head->val;
cout << "head: " << z << "\n";
prints
head: 1
head: -858993460
without even touching the getter. So is simply accessing l.head in any way enough to garble it?
No, as
int x = l.head->val;
int z = l.head->val;
cout << "head: " << x << "\n";
cout << "head: " << z << "\n";
returns (as intended) head: 1 two times. So using cout in between changes my objects or their pointers? And what's wrong with getHead() as all it does is just return head;?
So I'm pretty lost here and couldn't find any directly related questions. (This Question has a promising title but doesn't use pointers). Am I totally failing to use pointers in a correct way? Or is some automatic object deletion going on behind the scenes? Or is this just how magiC++ works?
In
void append(int i) {
head = &ListElement(i, head);
};
ListElement(i, head) creates a temporary, nameless ListElement and assigns a pointer to it to head. Then, because the ListElement itself wasn't assigned to anything, the ListElement goes out of scope and is destroyed. This leaves head pointing to invalid memory.
Head could be written to use dynamic memory to extent the life of the ListElement
void append(int i) {
head = new ListElement(i, head);
};
but now someone has to pick up the responsibility of ensuring that the ListElement is deleted when no longer required.
For example:
void remove(int i) {
// find list element i and previous element. Special handling required for first element
prev.next = element.next;
delete element;
};
Careful use of std::unique_ptr and std::move can get automate the memory management and eliminate the need for delete.
In C++ you must manage your own memory. The statement
ListElement(i, head);
Creates an instance of ListElement locally scoped the MyLinkedList::append(). Thus once that function exits the variable no longer exists and the pointer is now pointing at invalid memory.
The reason your first print statement is giving you a seemingly correct answer is a bit of a red herring. In all cases you are accessing free-ed memory which has undefined behavior. In the first case that memory just happens to have the value that you previously set.
You have to allocate your own memory in append and clean it up when you are done with it. Once you have mastered "new" be sure to look up how to iterate through a data structure and delete each element. With your linked listed implementation this should be fairly trivial.
change
void append(int i) {
head = &ListElement(i, head);
};
to
void append(int i) {
head = new ListElement(i, head);
};
The first, if it compiles, is taking the address of a temporary stack allocated object. Hence head will "point at garbage" after it's destruction.
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 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.