struct leaf
{
int data;
leaf *l;
leaf *r;
};
struct leaf *p;
void tree::findparent(int n,int &found,leaf *&parent)
This is piece of code of BST. I want to ask. why
leaf *&parent
Why we need "reference mark" here?
parent is also a leaf, why can't I just use leaf* parent?
code below for your reference. Thank you!
void tree::findparent(int n,int &found,leaf *&parent)
{
leaf *q;
found=NO;
parent=NULL;
if(p==NULL)
return;
q=p;
while(q!=NULL)
{
if(q->data==n)
{
found=YES;
return;
}
if(q->data>n)
{
parent=q;
q=q->l;
}
else
{
parent=q;
q=q->r;
}
}
}
You are passing the pointer parent in by reference, so that you can modify that pointer:
parent=q;
If you passed the pointer in by value, the modifications would be to a copy of the pointer that expires at the end of the function.
When you use REFERENCE TO POINTER, you can change the value of the pointer. You may need to use this schema in link list implementation to change the head of the list.
void passPointer(int *variable)
{
*variable = (*variable)*2;
variable = NULL; // THIS CHANGES THE LOCAL COPY NOT THE ACTUAL POINTER
}
void passPointerReference(int* &variable)
{
*variable = (*variable)*3;
variable = NULL; // THIS CHANGES THE ACTUAL POINTER!!!!
}
int main()
{
int *pointer;
pointer = new int;
*pointer = 5;
passPointer(pointer);
cout << *pointer; // PRINTS 10
passPointerReference(pointer);
cout << *pointer; // GIVES ERROR BECAUSE VALUE OF pointer IS NOW 0.
// The constant NULL is actually the number 0.
}
Related
i am c++ beginner student, i have a problem in my c++ lab assignment.
I have no ideas how to return a pointer to int from a pointer, which is pointer to the struct.
my header file
class list {
public:
/* Returns a pointer to the integer field
pointing to the first node found in list
with value val. Returns 0 otherwise */
int *find(int val);
private:
list_node *the_list;
}
my cpp file
int* list::find(int val)
{
while(the_list)
{
if(the_list->value == val)
{
// i try to return the pointer that is type pointer to int.
// the_list is a pointer to a struct type call list_node.
int * ptr = the_list;
return ptr;
}
the_list = the_list->next;
}
return 0;
}
struct list_node
{
int value; // data portion
list_node *next; // pointer next portion
list_node *previous; // pointer previous portion
};
the_list is not a pointer to int, it's a pointer to list_node, so int *ptr = the_list; is not correct.
To get a pointer to the value, do:
int *ptr = &(the_list->value);
Beware your find function moves the pointer to the internal list which is bad. You should use a private variable, and return the address of the value member:
int* list::find(int val)
{
for(list_node *node = the_list; node != nullptr; node = node->next)
{
if(node->value == val)
{
// i try to return the pointer that is type pointer to int.
// the_list is a pointer to a struct type call list_node.
return &node->value;
}
}
return nullptr;
}
I have a struct like this:
struct ClientNode
{
string name;
int flightnumber;
int clientno;
ClientNode * right;
ClientNode* left;
};
then I have declared a pointer of this struct:
ClientNode* root = new ClientNode;
in a function I have initialized clientno for root like this:
root->clientno = 11;
and then I want to send root as an argument to a function:
ClientNode newnode;
root = Insert_to_AVL_Tree(&newnode, root);
and here is my Insert_to_AVL_Tree:
ClientNode* clientclass::Insert_to_AVL_Tree(ClientNode* Node, ClientNode* root)
Here is where the error happens, I have initialized root->clientno but it seems that it changes when I pass it to another function thus it can't compare to values in the if, also node->clientno has the correct value that has been read from a file in another part of my code:
if (Node->clientno < root->clientno)
root->left = Insert_to_AVL_Tree(Node, root->left);
what is the correct way to get the root->clientno value in another function?
here is the value shown for root->clientno
here is the value for node->cleintno
For passing Pointer to functions the best way I use is double pointer
void clear(int **p)
{
*p = 0;
}
int main()
{
int* p;
clear(&p);
return 0;
}
When declaring a pointer variable, is there ever a use for more than one asterisk? I know when you want to have a pointer point to another you would use multiple, but just to clarify, when declaring you still only put one?
Weard things: an example of 3 asterisks:
const char **stringArray;
now, if you want to allocate this array in a function as an argument, you need the following:
void stringAllocator(const char ***stringArray, int size) {
*stringArray = (const char **) malloc(size);
}
...
stringAllocator (&stringArry, 20);
...
So, you can imagine more than 3 as well, though i had never saw more than 4 :-)
an a bit weirder stuff in c++ using stars in combination with &
void stringAllocator(const char **&stringArray, int size) {
stringArray = (const char **) malloc(size);
}
...
stringAllocator (stringArry, 20);
...
In the above case works as a star reduction technique. It does the same as the first examle
When declaring a pointer variable, is there ever a use for more than one asterisk?
Sure, there are uses for declarations of pointer to pointer variables.
Let's suppose you have a function that does allocate some class instance internally, but needs to indicate failure at the same time. You can give it a signature like
bool CreateSomeType(SomeType** pointerToSomeTypePointer) {
try {
*pointerToSomeTypePointer = new SomeType();
}
catch(...) {
return false;
}
return true;
}
and being called like this
SomeType* ptr = nullptr;
if(CreateSomeType(&ptr)) {
// Use ptr
// ...
delete ptr;
}
else {
// Log failure
}
A common use case of two stars is when a function has to alter a pointer value, e.g. in ADT implementations like "Stack".
Though this design is more C than C++ (in C++ you can use other mechanisms like references), see the following example. I wrote it in "C"-style (even if you mentioned C++):
struct node {
int x;
struct node* next;
};
// this one works:
void insertBeforeHead(node** head, int value) {
struct node* newNode = (struct node*)malloc(sizeof(struct node));
newNode->next = *head;
newNode->x = value;
*head = newNode; // alters the pointer value of the caller
}
// this one does not work:
void insertBeforeHead2(node* head, int value) {
struct node* newNode = (struct node*)malloc(new Node);
newNode->next = head;
newNode->x = value;
head = newNode; // alters only the local copy of the pointer value
}
int main () {
struct node* mainHead = NULL;
insertBeforeHead(&mainHead,10); // changes the value of mainHead
insertBeforeHead2(mainHead,20); // does not change the value of mainHead, althouth it should.
}
struct Node{
int value;
Node *next;
Node(int val) :value(val), next(nullptr){}
};
class Stack
{
public:
void push(int val);
int pop();
bool is_empty(){ return first == nullptr; }
private:
Node *first = nullptr;
};
int Stack::pop(){
int ret = first->value;
first = first->next;
return ret;
}
void Stack::push(int i){
if (is_empty()){
first = &Node(i);
return;
}
Node oldFirst = *first;
first = &Node(i);
first->next = &oldFirst;
}
Here is how I wrote the code, however, there is a problem that when I finished push() the pointer of first isn't point to the right object. I'm wondering how I can solve that problem.
The expression &Node(i) creates a temporary object and give you a pointer to it. And then the temporary object is immediately destructed, leaving you with a pointer to a non-existing object.
You need to use new to allocate a new object.
You have a similar problem with &oldFirst, which give you a pointer to a local variable, which will be destructed once the function returns. You need to use a pointer variable.
I am trying to remove the left child (10) of a sample binary search tree using two methods:
Method1: By passing pointer to a pointer to the current node.
Method2: By passing address of the pointer to the current node. This does not removes the node, but calling delete corrupts the pointer arrangement, causing a crash while printing the nodes.
The tree looks like this and I am trying to delete 10 and replace it with 5
20
|
10--|---30
|
5---|
I have some understanding of pointers. But still, I am not clear with this behavior of pointers.
#include <iostream>
class Node
{
public:
Node(int key) : leftChild(0), rightChild(0), m_key (key){}
~Node(){}
Node *leftChild;
Node *rightChild;
int m_key;
};
Node* build1234(int, int, int, int);
void print(Node *);
void print1234(Node *);
void removeLeft(Node **nodePtr)
{
Node *oldPtr = *nodePtr;
if(*nodePtr)
{
*nodePtr = (*nodePtr)->leftChild;
delete oldPtr;
}
}
int main()
{
Node *demo1 = build1234(10, 20, 30, 5);
Node *demo2 = build1234(10, 20, 30, 5);
print1234(demo1);
print1234(demo2);
//Method1 - 10 is correctly removed with 5
Node **nodePtr = &demo1;
nodePtr = &(*nodePtr)->leftChild;
removeLeft(nodePtr);
print1234(demo1);
//Method2 - 10 is not removed
Node *node = demo2;
node = node->leftChild;
removeLeft(&node);
print1234(demo2);
return 0;
}
Node* build1234(int B, int A, int C, int D)
{
Node *root = new Node(A);
root->leftChild = new Node(B);
root->rightChild = new Node(C);
root->leftChild->leftChild = new Node(D);
return root;
}
void print(Node *node)
{
if(node)
{
print(node->leftChild);
std::cout << "[" << node->m_key << "]";
print(node->rightChild);
}
}
void print1234(Node *node)
{
std::cout << std::endl;
print(node);
}
Note: This question is not about BST, but pointers. If you see the two calls to removeLeft(nodePtr) and the removeLeft(&node) in the main() function.
How are these two different?
Why the second method fails to achieve the desired result?
In the first case, you are passing an address of a pointer that exists in the tree, so you are modifying the contents of the tree directly.
In the second case, you are passing an address of a variable that is local to main() instead. The tree is not modified, and deleting from the address is accessing stack memory, which is why it crashes
You're overthinking it. All you need is a function removeLeft(Node*) that unhooks the left node and deletes it, recursively:
void removeLeft(Node * p)
{
removeBoth(p->leftChild); // recurse, OK if null
delete p->leftChild; // OK if already null
p->leftChild = 0; // necessary to make recursion terminate
}
void removeBoth(Node * p)
{
if (!p) return;
removeLeft(p);
removeRight(p);
}
If you are bad with pointers consider using smart pointers.
When using smart pointers use shared_ptr<Node> instead of Node * and make_shared(new Node); instead of new Node and remove all deletes. now you can handle pointers without caring for deletes and memory corruption.