Hi every body i have some question:
struct NODE{
TYPEDATA data;
NODE *link;
};
NODE* CreateNODE(TYPEDATA n){ //1
struct NODE *node = new NODE; //2
if(node){
node->data=n;
node->link=NULL;
}
return node;
}
1.why i must have * after NODE for CreateNODE
2.why must use new NODE
thank you
By using new, you dynamically allocate memory for a node. New returns a pointer to the allocated memory. You indicate that a variable is a pointer by using * . Since you want to return that new node, you need to return not a NODE, but a pointer to NODE, thus effectively the return type becomes NODE* . If you don't know how pointers or dynamic memory work, I suggest you look at these links:
pointers
dynamic memory
Related
I am currently working on a large data tree. I need to navigate the tree, return a subnode and change its value.
class Node {
short value;
std::vector<Node> children;
Node walk(int step) {
return children[step];
}
}
Will the return of the Walk function create a copy of the child Node or do I have to return a pointer? How should I Link the Nodes?
also another question:
what's the difference between these two and which should I use to create new nodes:
Node newNode;
// or
Node newNode = *new Node();
Edit
I tried std::vector<Node*> children; but this lead to memory leaks when deleting. Would Node& walk(int step) work too without using pointers?
To prevent memory leaks and keep your code clean, you can use shared pointers. Return weak pointer from walk function. We must return the weak pointer so as not to make the client the owner of a particular node.
#include<memory>
#include<vector>
class Node;
using NodePtr = std::shared_ptr<Node>;
using NodeWPtr = std::weak_ptr<Node>;
class Node {
short value;
std::vector<NodePtr> children;
NodeWPtr walk(int step) {
//Your Algorithm.
return children[step];
}
};
Node newNode = *new Node(); creates a Node on the heap and then copies it to a node on the stack. This however, has memory leak and it does not do anything significantly different than just creating a node directly on the stack.
Node newNode; creates Node object on the stack. I would suggest you use this as it directly describes your intent.
Some people have suggested the use of std::unique_ptr instead of std::shared_ptr because std::shared_ptr has a large overhead. However, if we do use std::unique_ptr, we would have to return an std::observer_ptr from the walk function which is not fully implemented in the latest c++ compilers as far as I know.
EDIT
The following 2 class designs are noteworthy of consideration according to the discussions in the comments.
//Without storing any pointers in the vector
class Node {
short value;
std::vector<Node> children;
Node* walk(int step) {
//Your Algorithm.
return &children[step];
}
};
or
//Using unique_ptr
class Node;
using NodePtr = std::unique_ptr<Node>;
class Node {
short value;
std::vector<NodePtr> children;
Node* walk(int step) {
//Your Algorithm.
return children[step].get();
}
};
In the code I copied newnode to the headnode and also to the temp node. But when I delete an instance of data, it seems to affect the other locations as well. When I freed newnode it also erases the content of head and temp .How is this happening?
Though I copied data initially, the data is freed. This is due to dereferencing? So what should I do if I want to have a copy list and want to manipulate this without affecting the original?
And I initially malloc'd the memory I want by malloc() but in later copy operations I see at codes they are not malloc()'ed rather just copied. And how is it still it working? Do my two questions have a relation?
#include <iostream>
#include <cstdlib>
using namespace std;
struct node{
int data;
struct node*next;
};
int main()
{
struct node*newnode=(struct node*)malloc(sizeof(struct node));
newnode->data=2;
newnode->next=NULL;
struct node*head=NULL;
head=newnode;
struct node*temp=newnode;
while(head!=NULL)
{
cout<<head->data;
head=head->next;
}
cout<<temp->data;
free(newnode);
free(head);
cout<<temp->data;
return 0;
}
With struct node *newnode=(struct node*)malloc(sizeof(struct node)); you allocate a piece of memory for a node once and then you assign the address of this memory to all other node pointers. So when you free this piece of memory, the node isn't available any more to any of the node pointers.
struct node *head=newnode; // head now points to *newnode
struct node *temp=newnode; // temp now also points to *newnode
...
free(newnode); // newnode, head and temp point to released memory now
free(head); // oops! head was released already by the previous statement
Note: this is the C explanation. In C++ the constructor of a class can do the memory allocation and a redefined assignment operator can create a new instance of the object (but I am not a C++ programmer).
The following function creates a copy of the list:
struct node *copylist(struct node *oldlist)
{
struct node *newhead, *list;
if (!oldlist) return(0);
list= newhead= malloc(sizeof(struct node));
*newhead= *oldlist;
while (oldlist->next) {
list->next= malloc(sizeof(struct node));
oldlist= oldlist->next;
list= list->next;
*list= *oldlist;
}
list->next= NULL;
return(newhead);
}
struct node {
string info;
node *next;
node() {
info = "string";
next = NULL;
}
};
void insert(node &anode) {
node newNode;
anode.next = &newNode;
}
What is wrong with this implementation of insert for this structure ? How should I fix this?
added: Very sorry that I wasn't clear. I know what is wrong with the program. I want to know how I can insert a new node to a reference node. Since I am using a reference to a node as a param this mean that node must not be a pointer? So its stored on stack? which means I can't use memory from heap? (or else seg fault?) so how am I suppose to use new ? This is my main confusion. Perhaps my approach is wrong but I don't see why it should be.
What's wrong is that newNode lives in the scope of the insert function. You probably want something like
void insert(node &anode) {
node* newNode = new node;
anode.next = newNode;
}
but the parent node, or something else, then has to take care of the new node's lifetime. It now owns the next node. If you want the caller to be in charge, then this might be more suitable:
void insert(node& parentNode, node& nextNode) {
parentNode.next = &nextNode;
}
Note that you can avoid some of the lifetime issues by using boost::shared_ptr or std::shared_ptr if you have access to C++0x. These smart pointers basically wrap a pointer and take care to delete it when nobody is using it. The code would look something like this:
struct node {
// other data members...
shared_ptr<node> next;
// constructors/destructors
};
void insert(node& anode) {
anode.next = shared_ptr<node>(new node);
}
Now you don't have to worry about deleting the new node at any point.
You're returning (implicitly, as member of anode) a pointer to the local variable newNode. newNode is destroyed when you're leaving insert, so anode.next contains an invalid pointer afterwards.
BTW: should this question be tagged "homework"? :)
The "what's wrong" has nothing to do with references.
This implementation stores a pointer to a local variable in anode.next. Local variable gets destroyed immediately afterwards (when insert function exists), while the pointer continues to live pointing into a destroyed location.
The problem is that the local variable newNode will go out of scope once the function insert exists, and anode.next will now reference an invalid node.
Assuming that you are talking about a runtime error. The problem is that in your insert function
node newNode
is only a local variable, and it will be causing a problem when you try to access it later while iterating on the node(s).
Inside the insert function you should be doing something like this:
node* newNode = new node();
anode.next = newNode;
If you insist on using free functions, your best bet is probably something like:
static node* head = NULL;
static node* current = NULL;
void insert(std::string& val)
{
if (!head) {
current = new node(val);
head = current;
} else {
current->next = new node(val);
current = current->next;
}
}
and having your constructor accept an std::string as an argument. Relying on an entity outside the function to create nodes for you is probably not the best idea. You can pseudo-encapsulate that by creating nodes on demand when you call insert. Then you can run through the nodes using the head pointer and consequently delete them when you're finished with the list.
You are using a static address.
void insert(node &anode) {
node newNode;
anode.next = &newNode;
}
newNode is a local object. At the end of the function, it will go out of scope and its address will be invalid.
Sorry if this question has been asked before. On my search through SO I didn't find one that asked what I wanted to know.
Basically, when I have this:
typedef struct node
{
int data;
node *node;
} *head;
and do node *newItem = new node;
I am under the impression that I am declaring and reserving space, but not defining, a pointer to struct node, is that correct?
So when I do
newItem->data = 100 and newItem->next = 0
I get confused. newItem = 0would declare what exactly? Both data and next? The object as a whole?
I'm especially confused when I use typedef. Which part is the macro? I assume node because that's how I call it, but why do I need it?
Finally, what happens when I do:
node *temp;
temp = new node;
temp = head->next;
head->next = newItem;
newItem->next = temp;
I mean, head->next is a pointer pointing to object newItem, so I assume not to newItem.data or next themselves. So how can I use an uninitialized pointer that I described above safely like here? is head now not pointing to an uninitialized pointer?
I am under the impression that I am
declaring and reserving space, but not
defining, a pointer to struct node, is
that correct?
No. You are declaring a pointer, allocating space on the stack for the pointer, and dynamically allocating storage for a node to it it.
Don't confuse yourself by writing stuff like this:
typedef struct node
{
int data;
node * next;
} *head;
The way to write the struct in C++ is:
struct node
{
int data;
node * next;
};
You can now create a pointer:
node * pnode;
which allocates storage for the pointer.
and you can dynamically allocate storage for a node, and make the pointer point to it:
pnode = new node;
or do it all in one:
node * pnode = new node;
Now when you say:
pnode->data = 10;
you are not allocating anything. You are assigning 10 to the member called data of the node instance pointed to by pnode. Of course, if you had given your node a constructor (which you should normally do), you could do it all in one:
struct node
{
int data;
node * next;
node( int n, node * np ) : data( n ), next( np ) {}
};
node * pnode = new node( 10, 0 );
When you define your struct as you did and call new like you did, what you're doing is:
allocate a new struct node on the heap.
allocate space on the stack for newItem and set its value to the address of the new struct you allocated.
You didn't set any values to any of the members of the new struct. If you want that to happen whenever you create a new instance of the struct, you need to define a constructor.
typedef struct node
{
int data;
node *node;
} *head;
This declares node as a struct and defines head as a synonym for node*, so head is a type and not an object.
This makes this illegal: temp = head->next; because -> is not something that you can apply to a type.
new node dynamically allocates a node object and returns a pointer to it. node *newItem = new node; assigns this pointer to newItem. Note, though, that newItem->node (node here is a pointer object and not the type node) is not initialized so is neither null nor points to a valid node object.
This is also illegal because node has no next member.
newItem->next = temp;
I suggest that you choose a naming convention that means that you keep your types and your variables separate. It is somewhat confusing.
node *newItem = new node;
You create:
a new node on the heap (which in your case contains uninitialized values because you omitted the ()
a pointer on the stack, which points to this new node.
newItem->data = 100
simply sets the data member of the newly allocated node to 100.
I'm attempting to craft my own basic singly linked list in C++ as a learning exercise, and I'm encountering some difficulty in the memory management department. As it stands I have...
A 'Node' class:
class Node
{
public:
char *value;
Node *next;
Node();
~Node();
};
Node::Node()
{
}
Node::~Node()
{
delete[] value;
}
And then my list (I've omitted certain method calls for brevity):
class LinkedList
{
private:
Node *head;
public:
LinkedList();
~LinkedList();
void Add(char **x);
};
LinkedList::LinkedList()
{
head = 0;
}
LinkedList::~LinkedList()
{
Node *temp;
Node *current = head;
while(current)
{
temp = current;
current = current->next;
delete temp;
}
}
void LinkedList::Add(char **x)
{
Node *nodeToAdd = new Node();
nodeToAdd->value = *x;
nodeToAdd->next = NULL;
Node *current = head;
if(!head)
{
head = nodeToAdd;
return;
}
while(current->next)
{
current = current->next;
}
current->next = nodeToAdd;
}
I'm attempting to use this code as follows (again I've omitted things for brevity):
int main()
{
LinkedList *list = new LinkedList();
char *alpha = "alpha";
char *beta = "beta";
char *charlie = "charlie";
char *delta = "delta";
char *echo = "echo";
list->Add(&alpha);
list->Add(&beta);
list->Add(&charlie);
list->Add(&delta);
list->Add(&echo);
delete list;
}
The last call in main to delete the list produces an error:
Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
What am I doing wrong here?
The data pointed to by the various Node::value aren't dynamically allocated, so you shouldn't delete them. Applying the concept of "ownership", nodes should either make their own copies of data, which they own and can delete, or nodes don't own data, so they shouldn't be responsible for deleting it.
You can also implement multiple ownership using reference counting, like Objective-C does (see Objective-C Memory Management Rules for more info) but you have to be careful to avoid ownership cycles. You often find some type of reference counting in third-party smart pointers, such as Boost's smart_ptr library. Since you're doing this for the learning experience, it may make more sense to roll your own than use a library. Of course, you could also use a library for now, letting you focus on whatever you're trying to learn.
One day a student came to Moon and said: “I understand how to make a better garbage collector. We must keep a reference count of the pointers to each cons.”
Moon patiently told the student the following story:
“One day a student came to Moon and said: ‘I understand how to make a better garbage collector...
you are trying to release the memory which is not allocated on heap.
char *alpha = "alpha"; --- not allocated on heap
calling delete[]in Node destructor would lead to heap corruption.
Some points:
1) initialize pointers properly in the constructor:
Node::Node():value(NULL),next(NULL)
{
}
2) Take a ownership of value.
Allocate the memory on heap and copy
the contents
You shouldn't release a pointer use delete[]/delete if it's not created by new operator. There are some actions under the hood for the delete[] operation, like releasing/reclaiming marked memory from a managed pool. Since your pointer doesn't belong to these stuff, there will be a problem. IMHO, the underlying delete[] code is the _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) stuff.
The problem is that you're assuming that you can delete the data inside node, but you're passing in pointers to string literals instead, which you can't delete.
If you're assuming that the Node object controls the lifetime of the data inside it, your Node constructor or the Add function in LinkedList will have to make a copy of the data that it is being passed.
In your destructor, you are trying to array delete (delete [ ]) a static string. You have change your Add function to reserve the string and copy it first. See the code below.
However, if I were you and fairly new to memory management, I'd really use something like CString instead of a raw "char *" as it's much easier to deal with.
void LinkedList::Add(const char *x)
{
Node *nodeToAdd = new Node();
int len=strlen(x);
nodeToAdd->value = new char [len+1]; // room for string + terminating 0
strcpy(nodeToAdd->value,x);
nodeToAdd->next = NULL;
Node *current = head;
if(!head)
{
head = nodeToAdd;
return;
}
while(current->next)
{
current = current->next;
}
current->next = nodeToAdd;
}
value and next in Node class doesn't have memory allocated. You should allocate memory in Node's constructor.