C++ pointer to class object [duplicate] - c++

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Passing pointer to local variable to function: is it safe?
(6 answers)
Closed 3 years ago.
I encounter a strange issue when using class in C++.
Here is my code to add object the my linked list. I found that my V1 code works correct but V2 code doesn't and the printList can never stop in V2. Do anyone can explain why it is the case, since I expect V1 and V2 code should output the same outcome.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node() {
cout << "Node object is being created" << endl;
}
};
void printList(Node *node) {
while(node != NULL) {
cout << node->data << ",";
node = node->next;
}
cout << endl;
}
void push(Node **node, int data) {
// // working V1 start
// Node *newNode = new Node();
// newNode->data = data;
// newNode->next = *node;
// *node = newNode;
// // working V1 end
// not working V2 start
Node newNode;
newNode.data = data;
newNode.next = *node;
*node = &newNode;
// not working V2 end
}
int main() {
Node *a = NULL;
push(&a, 15);
push(&a, 10);
printList(a);
}

Your V2 stores a pointer to a node in automatic storage. That node is automatically destroyed at the end of the push function at which point the pointer is left dangling and no longer points to a valid object.
When you later attempt to indirect through that pointer, the behaviour of the program is undefined.
V1 does not have this problem, since it allocates the nodes in dynamic storage. Instead, the problem with V1 is that it leaks the allocated memory. Dynamic allocations created with new-expression need to be deallocated with delete-expression.

The second code snippet has undefined behaviour because 1) the pointer newNode is not initialized and 2) you did not allocate memory where you are going to store values data and *node.
Node newNode;
newNode.data = data;
newNode.next = *node;
In the first code snippet a memory for the new node is allocated and the pointer is initialized by the address of the allocated memory
Node *newNode = new Node();
So these statements
newNode.data = data;
newNode.next = *node;
are valid and write data to the allocated memory.
Take into account that if to define the class the following way (removing the default constructor)
class Node {
public:
int data;
Node *next;
};
then the function can be written much simpler
void push( Node **node, int data )
{
*node = new Node { data, *node };
}

Related

Linked List Node object

class Node{
public:
int data;
Node* next;
Node(int data)
{
this->data = data;
this->next = NULL;
}
};
int main()
{
Node* node1 = new Node(12);
cout<< node1->data ;
return 0;
}
Can't understand that why are we creating pointer object for the node (Node* node1)?
Thanks for clearing my doubt in advance
The code in main() needs a pointer simply because that is what new returns. The code is creating the Node object in dynamic memory on the heap (and consequently leaking it, since there is no delete node1; statement before the return statement).
You could instead create the object in automatic memory on the stack, and thus not need a pointer, eg:
int main()
{
Node node1(12);
cout << node1.data;
return 0;
}
Typically, linked lists are created using dynamic memory so that new nodes can be added to the list dynamically, such as in a loop, or in response to user input, etc.

Value in a portion of memory is changed due to declaration [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
How to initialize a local struct object in C++ (cannot create a new object as a local variable)?
(1 answer)
Closed 1 year ago.
My background: I didn't read too much about memory allocation through stack and heap, but stack allocation it's 'casually' said to be faster. I think that when you create an object with new keyword you are using somehow heap allocation, I don't expect it when I just do
A a;.
Problem:
I'm trying to implement a linked list in C++ with the possibility to insert an element in any position nth. For this I implemented a flag, that would help control the position, but when i use this declaration the data in my head pointer changes. I reduced the original code, but the following resumes the problem:
#include <iostream>
struct node {
int data;
node* next;
node* prev;
node(int dat) { data = dat; next = nullptr; prev = nullptr; }
};
struct Linked_list {
node* head;
node* tail;
Linked_list(int data) {
node init(data);
head = &init;
tail = &init;
}
void insert() {
node* iterator = head;
std::cout << head->data;
int flag = 0;
//prints -858993460 if we declare the flag.
//If flag declaration doesn't exist prints 12;
}
};
int main()
{
Linked_list A(12);
A.insert();
}
Why is this happening? I really need to implement it dinamically?

HOW ARE Node a and Node* s different?

struct Node
{
int w;
Node* w1;
};
int main(){
Node a;
Node *s;
}
In above code what is difference between a and *s. How are they different.Also why we use Node *s while creating a LinkList.
THANK YOU!!!
Node a is an object. It allocates some space in memory.
Node *s1 - is pointer to object of type Node, but the object itself must be created with, for example, a new operator. Or we must explicitly take and address of the object with & operator. It is just a variable that holds an address. The size of this variable depends on platform (4 bytes on x86, 8 bytes on x86_64).
Each node of a Linked list stores a pointer to the next node. That is why we need a pointer here. Thus if you you have access to the node, you can travel to the next and to the end of the list.
Disclaimer: The given code is very basic and given for explanation only. This is not how you create linked list in real-life. Manually connecting nodes is not a great pattern. I would recommend you to learn more about basic language concepts like pointers, references, object lifetime.
// Node type definition
struct Node
{
int w;
Node* w1;
};
int main() {
// Separate nodes
Node n1;
Node n2;
Node n3;
// Now this is a linked list
n1.w1 = &n2;
n2.w1 = &n3;
n3.w1 = nullptr; // to mark the end
// Get pointer to n2 from n1
Node *n2_ptr = n1.w1;
Node *n3_ptr = n2.w1;
// Check if n3 is the last element
if (n3_ptr->w1 == nullptr) {
// this is the end of the list
}
// walk the list
Node *node = &n1;
while (node != nullptr) {
node->w *= 2; // do smth with data
node = node->w1; // go to the next node
}
return 0;
}

c++ constructor seems to return pointer to the same object every time [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
I have a simple implementation of a Linked list class, which has pointers to Node objects which I have also defined.
The function insertHead creates a new Node and inserts it at the head.
However, whenever I call the function, the constructor seems to return a pointer to the same object every time. (I checked that using GDB)
I am pasting snippets of the code here. Can someone please let me know if something seems off?
void LinkedList::insertHead(int val){
Node temp(val);
if(head == NULL){
head = tail = &temp;
} else {
temp.setNext(head);
head = &temp;
}
}
Class definitions:
class LinkedList{
Node *head;
Node *tail;
...
class Node{
int val;
Node *next;
...
Node::Node(int x){
val = x;
next = NULL;
}
You cant assign address of automatic storage variable and use it out of the body, becouse it got out of scope (undefined behaviour). You need to dynamically allocate space on heap for the node.
Node * temp = new Node(val);
if(head == NULL)
{
head = tail = temp;
} else {
temp.setNext(head);
head = temp;
}
And in destructor free all nodes.
You need to allocate your nodes on heap rather than stack. (I encourage you to read about those two). Also please use nullptr instead of NULL if supported ( > c++11)
void LinkedList::insertHead(int val){
Node* temp = new Node(val);
if(head == nullptr){
head = tail = temp;
} else {
temp->setNext(head);
head = temp;
}
}
This will also require you clean up the nodes properly using the delete to avoid memory leaks which will most probably require adding a custom destructor to your list class, something along those lines:
LinkedList::~LinkedList() {
Node* node = head;
while(node != nullptr) {
Node* toDel = node;
node = node->next;
delete toDel;
}
}

struct containing string value causes segmentation fault upon its assignment after its creation using dynamic memory allocation

The compiler throws runtime segfault upon following code :
#include <iostream>
#include <string>
using namespace std;
struct Node{
int data;
void *next;
string nodeType;
};
Node* initNode(int data){
Node *n = (Node*)malloc(sizeof(Node));
n->data = data;
n->next = NULL;
n->nodeType = "Node"; //if this line is commented it works else segfault
return n;
}
int main() {
Node *n1 = initNode(10);
cout << n1->data << endl;
}
Can someone please explain why string assignment does not work inside a struct which is dynamically allocated where in case of static allocation why it works ?
where as the following way it works :
Node initNode(string data){
Node n;
n.data = data; //This works for node creation statically
n.next = NULL;
n.nodeType = "Node"; //and even this works for node creation statically
return n;
}
and then in the main function:
int main() {
Node n2 = initNode("Hello");
cout << n2.data << endl;
}
This doesn't work because you don't actually construct a Node instance into the memory which you malloc.
You should use new instead:
Node *n = new Node{};
malloc only allocates memory, it has no idea what a class is or how to instantiate one. You should generally not use it in C++.
new allocates memory and constructs an instance of the class.
There is no place, where std::string constructor is executed.
You should use new
example *e = new example;
or placement new
void *example_raw = malloc(sizeof(example));
example *e = new(example_raw) example;
Node *n = (Node*)malloc(sizeof(Node));
This cast is nonsense. You can't just tell the compiler to pretend that a chunk of data you just allocate contains a valid Node object and then manipulate it.
string in c++ is an class and to create string objects use new instead of malloc as below .
Node *n = new Node{};