Okay so I have a class, LinkedList, with a nested class, LinkedListIterator. Within LinkedListIterator's methods I reference the private fields of LinkedList. Which I thought was legal. But I get the error:
from this location
every time I reference them.
And I get corresponding error messages on the fields in the enclosing class:
invalid use of non-static data member 'LinkedList<int>::tail'
Any idea why? The relevant code is below:
template<class T>
class LinkedList {
private:
//Data Fields-----------------//
/*
* The head of the list, sentinel node, empty.
*/
Node<T>* head;
/*
* The tail end of the list, sentinel node, empty.
*/
Node<T>* tail;
/*
* Number of elements in the LinkedList.
*/
int size;
class LinkedListIterator: public Iterator<T> {
bool add(T element) {
//If the iterator is not pointing at the tail node.
if(current != tail) {
Node<T>* newNode = new Node<T>(element);
current->join(newNode->join(current->split()));
//Move current to the newly inserted node so that
//on the next call to next() the node after the
//newly inserted one becomes the current target of
//the iterator.
current = current->next;
size++;
return true;
}
return false;
}
You can't just use non-static members like that. I think the following example will clear things out:
LinkedList<int>::LinkedListIterator it;
it.add(1);
What would current and tail be inside the method? There's no instance of LinkedList to speak of, so those members don't even exist yet.
I'm not saying make the members static, that would be wrong, but re-think your approach.
Look into how std iterators are.
Related
here i simply wanted to print the elements of the linked list i created but it is printing the list in REVERSE order. looks like there is a mistake in the code.help me solve it
push function adds node to linked list every time we input element to be inserted in linked list.I've passed reference of head and data. A node gets dynamically created every time push fuction called. I am using c++ here.
#include<iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
//creating linked list
void push(node** head_ref,int new_data) //passing address of head and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
new_node->next=*(head_ref);
*(head_ref)=new_node;
}
int main()
{
node* head=NULL;
int n;
cin>>n; //number of elements in linked list
for(int i=0;i<n;i++)
{
int val;
cin>>val;
push(&head,val); //push function which creates a linked list
}
//while loop for printing elements of linked list
while(head!=NULL)
{
cout<<head->data;
head=head->next;
}
return 0;
}
What you currently do is assigning each node to be the predecessor of the current head, so in the end your head will be the latest element you added , its successor the second last element, its successor the third last element etc. and thus resulting to a reversed list.
You should assign the new node as successor of the current "head", like this:
void push(node** tail_ref,int new_data) //passing address of tail and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
(*tail_ref)->next= new_node;
*(tail_ref)=new_node;
}
Note that I renamed head_ref to tail_ref in the snippet above, which better describes what the pointer actually represents: a pointer to the current last element of the list, hence the tail of the list.
Of course, you will need to save the pointer to the first element. Otherwise you won't be able to iterate through your linked list.
Extension to Simon's answer, which is correct so far:
You already have a class 'node' – why not create a class 'list' or 'linked_list' as well:
class LinkedList
{
node* m_head = nullptr;
node* m_tail = nullptr;
};
Now you always have head and tail combined and don't need to store them separately. Note that in above example, they are both private. That's actually how you should design your class. If you don't, then you allow a user to break the list implementation from outside (someone might, for instance, just set one of these pointers to nullptr, producing a memory leak in case of head).
However, now you will have to provide appropriate means to access and modify the list:
class LinkedList
{
public:
void append(int new_data); // as Simon proposed
void prepend(int new_data); // your implementation
int head();
int tail();
void dropHead();
//void dropTail(); // is an O(n) operation with singly linked list, though!
private:
node* m_head = nullptr;
node* m_tail = nullptr;
};
The node class is very closely linked to your list, you might consider not letting it be a stand-alone class, but making it a nested class instead. There's yet quite a bit to add (e. g. how to iterate over the list). To get some hints I recommend to peek a bit into STL and get familiar with the concept of iterators.
Finally: Stop re-inventing the wheel. STL already provides fully implemented doubly (std::list) and singly (std::forward_list) linked lists. It's fine to experiment with an own implementation to get to know how the winds blow, but once you know, switch back to STL.
How to deal with memory leaking with template classes in C++?
In this code I defined 4 template classes:
class node and class linked_list make up a doubly linked list
class item and class bag just make up another doubly linked list
These template classes are designed to deal with objects of various classes.
In the main function, I first created a linked_list<string> and a bag<int> and everything is fine.
But when I try to make a bag<linked_list<string>>, problems arise.
I tried to trace back to see what happened, and I saw that in the function push_back in class bag, a destructor of linked_list has been called that erased all the data in the input v. I don't know why that happens.
Note that I overwrote the destructors for all classes and called className.~className() in the main function to prevent memory leaking.
And it does work to prevent memory leaking from ls_1 and bag_1.
I don't know which part of my code is wrong. Can somebody help me?
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
//node and linked_list class make up a doubly linked list
template<class T> class node {
public:
T value;
node<T> * next;
node<T> * previous;
node<T>() { next = nullptr; previous = nullptr; }
node<T>(T v) { value = v; next = nullptr; previous = nullptr; }
~node<T>() { delete next; }
};
template<class T> class linked_list { //doubly linked list
public:
node<T> * head;
node<T> * tail;
linked_list<T>() { head = nullptr; tail = nullptr; }
~linked_list<T>() { delete head; }
void push_front(T v) { //insert an item to the front
node<T> * p = new node<T>(v);
p->next = head;
head = p;
if (tail == nullptr) {
tail = p;
}
}
};
//item and bag class just make up another doubly linked list
template<class X> class item {
public:
X value;
item<X> *next;
item<X> *previous;
item<X>(X v) { value = v; next = nullptr; previous = nullptr; }
~item<X>() { delete next; }
};
template<class X> class bag { //just another doubly linked list
public:
item<X> *last;
item<X> *first;
int num_items;
int size() { return num_items; }
bag() { last = nullptr; first = nullptr; num_items = 0; }
~bag() { delete first; }
void push_back(X v) { //insert an item to the back
item<X> * p = new item<X>(v);
if (num_items == 0) {
last = first = p;
}
else {
last->next = p;
p->previous = last;
last = p;
}
num_items++;
last->next = nullptr;
}
};
int main() {
//When using built-in classes (like strings) as input
//there's no problem at all
linked_list<string> ls_1;
ls_1.push_front("David");
ls_1.push_front("John");
bag<int> bag_1;
bag_1.push_back(1);
bag_1.push_back(2);
//Problems arise here when using user defined classes (linked_list) as input
//I traced back and found out that a destructor has been called
//that erases all the data in the input. Donno how that happens
bag<linked_list<string>> bag_string;
bag_string.push_back(ls_1);
//These lines are to prevent the memory leaking
//I overwrote destructors for linked_list and node class
//otherwise there's still memory leaking
ls_1.~linked_list();
bag_1.~bag();
bag_string.~bag();
_CrtDumpMemoryLeaks();
getchar();
getchar();
}
Implement node, linked_list, item, bag copy constructors and assignments or declare them as deleted. The default versions generated by the compiler do not do the deep copying and that leads to multiple deletes of same objects after they were copied.
Read the rule of three/five/zero for full details.
A bit off-topic, but making a list node delete its siblings is a classic gotcha: for a sufficiently long list it ends up calling ~node<T>() recursively until it exhausts the stack. And this is the reason node pointers cannot be smart-pointers.
A fix would be to have a default destructor for nodes and make the list destroy the nodes in a loop, rather than recursively.
You may also like to use the full list node as a head of the list that points to itself when empty. That removes that nullptr checking logic completely.
I tried to trace back to see what happened, and I saw that in the function push_back in class bag, a destructor of linked_list has been called that erased all the data in the input v
Yes, this happens because your bag::push_back() takes its argument by value. This means it creates a copy of the ls_1 you created in main. You have not specified how to "copy" a list, so the compiler generated this function (a copy constructor) automatically. It can do that because your linked_list only contains two pointers, so the compiler assumes (because you have not told it otherwise) that copying the pointers over is all that is necessary to generate a copy of a linked_list. Unfortunately, that is not correct.
You now have two lists that manage the same contents: The original ls_1 in main() and the function argument v in push_back() - they both contain the same pointers.
Then the same thing happens again in your item constructor: You make a local copy of the list that holds the same pointers as the first two.
You now have several list objects pointing to the same data. Each one will try to destroy the data once it dies. This results in undefined behavior.
To correct this, you need to figure out how copying of a list should work. This is (in part) what the rule linked in the other comment is about: If the destructor of your class is not trivial (i.e. the compiler-generated version would not be sufficient, most likely because you need to release a resource like allocated memory), you should/must always care about how to handle your class being copied around. The various mechanisms that may invoke copy-like behavior (assignment, copy constructor, plus move versions in newer C++) need to be specified (or forbidden) by you.
I'm trying to pass in a head node to a function that recursively deletes everything from the LLL. But I'm not very good with classes. I've got one class for the LLL data called Node, and another called NodeList which manages all of the nodes.
The problem is that I can't access the private fields and I don't know how to get them in there. Because I don't want them public like a struct.
C++ Having trouble with syntax, so a class can pass data to other classes I've checked this link which said to make sure to have in the NodeList class Node * head, but I already have that.
C++ passing private data to other private functions in a class And I checked this one, but it was way over my head for the little C++ I know. Also I think this was just a pass by refrence issue.
This isn't the whole thing by the way, just the classes and the one function.
class NodeList
{
public:
NodeList();
~NodeList();
//this should delete the whole list
void delList(NodeList * head);
private:
//head
NodeList * head;
};
//this is the nodestructkindathing
class Node
{
public:
Node();
~Node();
private:
//next pointer
Node * next;
int data;
};
void NodeList::delList(NodeList * head)
{
if (!head)
return;
delList(head->next);
delete head;
}
NOTE: I changed delList and Node * head in the class to become NodeList * head and now I only recieve one error.
error: ‘class NodeList’ has no member named ‘next’
As suggested by Some programmer dude, make NodeList a friend of Node. When class A declares class B to be a friend, B can see and interact with the private members of A. Note that the reverse is not true. friendship is one way. A cannot see the private members of B unless B declares A to be a friend.
This one change will solve all of the problems asked in the question.
The rest of this code dump is to make writing a linked list a little easier for you. Linked lists are best considered a rite of passage for programmers. You'll find you rarely use them in real life programming, but they serve as a notorious weeder of CS students. Practically no one gets them right the first time or two. They require a moderate amount of care and attention to book keeping. Pen and paper step-by-step drawings of the list and the interactions you wish to perform on the list are highly recommended to help visualize and debug a linked list.
You may also find delving into pointers to pointers extremely helpful. For example, see the Alternative Using Pointer To Pointer section of this linked answer.
Comments embedded where needed.
#include <iostream>
class Node
{
friend class NodeList; // NodeList, and no one else, can now see the private
// members of Node
public:
// Node must be given a value and it not given a next, it's automatically NULL
// this makes it almost impossible to not point link at something useful,
// eliminating the most common of the trivial linked list bugs
Node(int value, Node * link = nullptr);
~Node(); //if it doesn't do anything. Get rid of it. See the Rule of Zero
private:
//next pointer
Node * next;
int data;
};
class NodeList
{
public:
NodeList();
~NodeList();
//this should delete the whole list
void delList(Node * head);
private:
//head
Node * head;
};
Node::Node(int value, Node * link) : next(link), data(value)
{
// test code
std::cout << "Node data = " << data << " next = " << next << '\n';
}
Node::~Node()
{
// test code
std::cout << "~Node data = " << data << '\n';
}
NodeList::NodeList()
{
// test code to give delList something to delete
head = new Node(1,new Node(2,new Node(3)));
}
NodeList::~NodeList()
{
delList(head);
}
//this is the nodestructkindathing
void NodeList::delList(Node * head) // watch out! Parameter head shadows member head!
{
// Warning: This function is recursive and a potential stack-killer if given a
// long list. Prefer iteration here unless given a reason to do otherwise
// and guarantees on maximum list length
if (!head)
return;
delList(head->next);
delete head;
}
int main()
{
NodeList test;
}
Expected output:
Node data = 3 next = 0
Node data = 2 next = 0x2ec6cc0
Node data = 1 next = 0x2ec6ce0
~Node data = 3
~Node data = 2
~Node data = 1
A discussion of the Rules of Three, Five and Zero. Understanding these rules is a must if you want a stable linked list or to program non-trivial systems in C++.
Documentation on friend.
I am studying C++ from Herbert Schildt's book "Teach Yourself C++ 3rd Edition". In one example code, something made me so confused.
#include <iostream>
using namesapce std;
template <class data_t> class list {
data_t data;
list *next;
public:
list(data_t d);
void add(list *node) {node->next = this; next = 0; }
list *getnext() { return next;}
data_t getdata() { return data;}
};
I didn't write all code in example, I only writed class declaration.
In here, I didn't understand one part. First, the "*node" pointer which belongs to "add" function, is using as "node->next" for "*next" pointer. I didn't understand the aim in here, why we don't directly use like {"next=this; next=0;} ? Also, how can we use an empty pointer (*node) to point another empty pointer (*next) ? I am missing maybe some key concepts, thanks for helps.
In the function add():
template<typename data_t>
class list {
// ...
void add(list *node) {node->next = this; next = 0; }
// ...
};
The point of the function is to add this to the list, as the next element after node. Think about it like a train: add() tells the current car to hook itself onto the back of another car, with the function's parameter telling it which car to link to.
Note that this function expects node to not be a null pointer; if it is null, you'll probably get a segmentation fault.
void add(list* node) {
node->next = this; // Tells "node" to register the current node as its "next" node.
// Should first check whether "node" is a valid pointer.
next = 0; // Tells the current node to register a null pointer as its "next" node,
// signifying that it's currently the last node in the list.
// Note that instead of assigning 0, it should instead assign either
// "nullptr" (C++11 or later) or "NULL" (pre-C++11).
}
Therefore, when used like this:
list<int> start(42), second(24);
second.add(&start);
It will do the following:
(&start)->next = &second;
(&second)->next = 0;
This creates a singly linked list, which looks like this:
Start: "start"
--> Next: "second"
--> Next: None.
Or, more concisely:
start->second->NULL
Remember, when inside a non-static member function, any member variable accesses are assumed to operate on this unless otherwise specified.
template<typename data_t>
void list<data_t>::add(list* node) {
node->next = this; // Operates on node, not on this.
next = 0; // Operates on this; becomes "this->next = 0;"
}
If this function intstead was just {next = this; next = 0;}, then it would be:
template<typename data_t>
void list<data_t>::add(list *node) {
this->next = this; // Bad. Creates a circular linked list, where "this" is ALWAYS the
// next node after "this".
this->next = 0; // Renders the above line entirely pointless, by indicating that there
// are no nodes after "this".
}
Let's say I'm using a non-standard linked-list class, List.h. This class is functioning, template'd and has the typical features of add/remove to front and add/remove to back, isEmpty(), etc.
This list does not have any begin() and end() functionality. Also, does a linked-list class have to include iterator functionality? Or is that something I can create on my own when I create a new List?
I'm used to working with STL, so I would usually use this code:
typedef vector<OBJECT>::iterator QuoteIt;
for(QuoteIt i = deposits.begin(); i != deposits.end(); ++i)
Anyway, lets say I create a new "List".
List<int>deposits;
or even a List of Objects
List<OBJECT>deposits;
So let's say I addToBack() 20 different integers, so that creates the appropriate # of new nodes.
Now, how can I traverse this list so I can find a sum of all these ints? Is that possible, or does my current functionality prevent that? I would have to implement some sort of iterator to my List Class?
Now I know I could keep an outside variable, every time I do an addToBack() call to keep track of my sums. However, I want the code to be compatible with Lists of Objects as well. (I want to be able to search one value in a node, and retrieve another value in the same node eventually)
I'm so used to working with stl::list and creating a for loop with iterators, I really dont' know how to get this working with other classes.
btw here is the code for List():
template<class NODETYPE>
class List{
public:
List();
~List();
void insertAtFront(const NODETYPE &);
void insertAtBack(const NODETYPE &);
bool removeFromFront( NODETYPE &);
bool removeFromBack( NODETYPE &);
bool isEmpty() const;
private:
ListNode< NODETYPE > *firstPtr; //pointer to first node
ListNode< NODETYPE > *lastPtr;
//Function to allocate a new node
ListNode< NODETYPE > *getNewNode ( const NODETYPE &);
};
//default constructor
template <class NODETYPE>
List< NODETYPE > ::List()
: firstPtr(0),
lastPtr(0)
{
cout<<"Creating Nodes! \n\n!"<<endl;
}
//deconstructor
template <class NODETYPE>
List<NODETYPE>::~List(){
if(!isEmpty() ){
cout<<"Destroying nodes!"<<endl;
ListNode<NODETYPE> *currentPtr=firstPtr;
ListNode<NODETYPE> *tempPtr;
while( currentPtr !=0){
tempPtr = currentPtr;
currentPtr=currentPtr->nextPtr;
delete tempPtr;
}
}
cout<<"All nodes destroyed! \n\n";
}
template <class NODETYPE>
bool List <NODETYPE>::removeFromFront( NODETYPE & value){
if ( isEmpty() )
return false;
else{
ListNode<NODETYPE> *tempPtr = firstPtr;
if (firstPtr== lastPtr)
firstPtr=lastPtr = 0;
else
firstPtr=firstPtr->nextPtr;
value = tempPtr->data;
delete tempPtr;
return true;
}
}
template <class NODETYPE>
bool List<NODETYPE>::removeFromBack(NODETYPE &value)
{
if (isEmpty())
return false;
else{
ListNode< NODETYPE> *tempPtr = lastPtr;
if( firstPtr == lastPtr)
firstPtr = lastPtr = 0;
else{
ListNode<NODETYPE> *currentPtr=firstPtr;
//Finds second to last element
while(currentPtr->nextPtr !=lastPtr)
currentPtr=currentPtr->nextPtr;
lastPtr = currentPtr;
currentPtr->nextPtr=0;
}
value = tempPtr->data;
delete tempPtr;
return true;
}
}
//Checks to see if list is empty
template< class NODETYPE>
bool List< NODETYPE >::isEmpty() const{
return firstPtr == 0;
}
//returns a pointer to newly created Node
template<class NODETYPE>
ListNode<NODETYPE> *List<NODETYPE>::getNewNode(const NODETYPE &value){
return new ListNode<NODETYPE>(value);
}
In response to:
Now, how can I traverse this list so I can find a sum of all these ints? Is that possible, or does my current functionality prevent that? I would have to implement some sort of iterator to my List Class?
You need to implement a way to iterate over your list that does not (as a side-effect) destroy your list.
In response to:
Now, how can I traverse this list so I
can find a sum of all these ints? Is
that possible, or does my current
functionality prevent that? I would
have to implement some sort of
iterator to my List Class?
No matter how you design a linked list, you must have some sort of pointer to the beginning of the list, and you have to have a way of knowing when you are at the end (e.g. when "next" is null, or by having a pointer to the end). By exposing those data one way or another, you can always set up a list traversal:
Start at the beginning. (In your case, get a hold of firstPtr.)
If you are not at the end, move to the next element. (In your case, get ->nextPtr.)
Using that pattern to accumulate a value as you visit each element you should be able to handle your task with ease.
If your list does not give you public access to its beginning, then it is certainly not a general-purpose list!
You can approach this many ways. You can either choose to create your own iterator or give public access to the list's head.
Option 1 is compatible with stl lists so you might want to go that route. An iterator is essentially a ptr that overrides the inc and dec operators to go to the next or previous position in the list.
If you studied basic data structures at all, you would know that traversing a list is trivial.
Node<type> t = head;
while (t != NULL)
{
// process node here
t = t->next;
}
The code can differ depending on if you use dummy nodes at all.
Since there is no functionality to just get the node without removing it from the list, you can't simply make an "add-on" iterator without changing the List class. The least you would need to do is to either
friend the external ListIterator class
friend free begin and end functions
add begin and end functions to the List class
Without any of those three, you can't achieve what you want.
Your list seems to have 2 ways of iterating it (forwards and backwards)
List<int>deposits;
.. add stuff:
int o;
int sum = 0;
while(deposits.removeFromFront(o)) {
sum+=o;
}
The bad thing though, is that iterating it, you also destroy the list,
you could provide public accessors to List::firstPtr and ListNode::nextPtr in which case you could do:
List<int>deposits;
.. add stuff:
int sum = 0;
for(ListNode<int> *ptr = deposits.firstPtr; ptr ; ptr = ptr->nextPtr)
sum+=ptr->data;
However, use an existing STL container if you can.