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.
Related
can someone run this code and tell me why the node in insert keeps overwriting?
#ifndef LinkedList_hpp
#define LinkedList_hpp
#include <stdio.h>
#include <utility>
template<class T>class LinkedList{
public:
LinkedList(){
head = nullptr;
tail = nullptr;
size = 0;
}
//void insert(T val);
class Node{
public:
Node* next;
T* value;
Node* prev;
Node(T* value){
this->value = value;
}
Node(){
}
Node(T* value,Node* prev, Node* next){
this->value = value;
this->next = next;
this->prev = prev;
}
Node* operator=(const Node& node){
this->value = node.value;
this->prev = node.prev;
this->next = node.next;
return *this;
}
};
public:
Node* head;
Node* tail;
int size;
void insert(T val){
at this line, if the previous head was 10, the current val, 40, overwrites the old head value and inserts a new node with val 40
Node* temp = new Node(&val);
if(head==nullptr){
head = temp;
tail = temp;
}else{
temp->next = head;
head->prev = temp;
head = temp;
}
size++;
}
#endif
#include <iostream>
#include "LinkedList.hpp"
int main(int argc, const char * argv[]) {
// LinkedList<int> t;
int h = 7;
int j = 10;
int k = 40;
LinkedList<int>* list1 = new LinkedList<int>();
list1->insert(h);
list1->insert(j);
list1->insert(k);
return 0;
}
every time insert is called and a new node is constructed, it overwrites the old value and everything becomes the current Val
void insert(T val){
val is a parameter to this function. This object, this val, only exists until this function returns. At which point it gets destroyed, like everything else declared in non-static scope inside the function. That's how C++ works. Once insert() returns, this val no more. It ceases to exist. It goes to meet its maker. It becomes an ex-object, that no longer exist and is completely in the past.
Your insert() function does the following:
Node* temp = new Node(&val);
You're passing a pointer to this val parameter to Node's constructor, and Node then saves the pointer to a parameter to insert(), as its own class member.
That's great, but as soon as insert() returns, the saved pointer in the new-ed Node becomes a pointer to a destroyed object, and dereferencing this pointer becomes undefined behavior.
You are then, later, attempting to dereference the original pointer, which is no longer pointing to a valid object.
This explains the observed undefined behavior in your code.
The bottom line is that your classes and templates's design is fundamentally flawed. There is no apparent purpose for Node to use a pointer. Node should simply store T as its own class member, as the value, instead of value being a pointer to some other T which exists somewhere, and can get destroyed at any time, which is not under Node's control.
Another problem in the shown code is that two ofNode's constructor fail to initialize the next and prev pointers to NULL. This will also lead to undefined behavior.
void insert(T val)
takes its arguments by value, so val is a local copy rather than the original.
Node* temp = new Node(&val);
stores a pointer to this local copy. The copy goes out of scope, so what you're looking at after insert exits is a ghost existing in memory that is no longer valid. In this case the ghost appears to always hold the last value set.
Solution:
Smart way: Store Node::value directly instead of as a pointer that you need to keep alive along with the node. Much less memory management this way.
T* value;
becomes
T value;
and
Node(T* value){
this->value = value;
}
becomes
Node(T value){
this->value = value;
}
The other uses of value must be updated accordingly. In general, new is such a headache that it should be used sparingly.
Stupid way: Pass by reference
void insert(T &val)
so that the pointer points at the longer lived original.
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;
}
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.
}
I am confused with what exactly goes wrong in the following demo code. I expected that the next would keep pointing to the next element in the chain until reached end. However, I get EXE_BAD_ADDESS error. I guess I am missing something in the recursive pointer assignment.
template <class T>
struct Node {
Node *left, *right, *parent;
int height;
T value;
// constructor
Node(T val)
: value(val){
height = 0;
left = right = NULL;
}
};
template <class T>
void assignToNext(Node<T> *n, Node<T> *next){
// base case
if (n == NULL)
return;
// else assign to this node and check for next
next = n;
assignToNext(n->left, next);
}
And then in the main:
Node<int> a(1);
a.left = new Node<int>(2);
a.left->left = new Node<int>(3);
a.left->left->left = new Node<int>(4);
a.left->left->left->left = new Node<int>(5);
Node<int> *last = NULL;
assignToNext(&a, last);
std::cout << last->value << std::endl; // I get EXE_BAD_ADDRESS error
Thanks in advance,
Nikhil
void assignToNext(Node<T> *n, Node<T> *next){
-->
void assignToNext(Node<T> *n, Node<T> *&next){ // note the &
Otherwise the original pointer isn't updated and stays NULL.
assignToNext(&a, last);
This code can't modify local variable Node<int> *last's value. You just passed NULL to parameter Node<T> *next. So last's value is still NULL and you got error. If you want modify pointer's value, use double pointer.
Like,
void assignToNext(Node<T> *n, Node<T> **next);
assignToNext(&a, &last);
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.