Accessing class member pointers - c++

Suppose I have the following definition of List and Node:
template <class T>
class List {
public:
class Iterator;
class ConstIterator;
//Constructors and Destructors.
List() : head(NULL), tail(NULL), size(0) {}
List(const List& list);
~List();
//Methods
Iterator begin();
ConstIterator begin() const;
Iterator end();
ConstIterator end() const;
void insert(const T& data);
void insert(const T& data, const Iterator& iterator);
void remove(const Iterator& iterator);
int getSize() const;
Iterator find(const T& item);
ConstIterator find(const T& item) const;
void sort();
//Operators
List operator = (const List& list);
private:
class Node;
Node* head;
Node* tail;
int size;
};
template <class T>
class List<T>::Node
{
public:
//Constructors and destructors
Node(const T& _data, const Node* _next) : data(_data), next(_next) {}
~Node(); //Destructor
//Methods
//Operators
Node operator = (const Node& node);
private:
T data;
Node* next;
};
I'm writing a function to insert data into a list like this:
template<class T>
void List<T>::insert(const T& data)
{
Node newNode = new Node(data, NULL);
if (head == NULL)
{
head = &newNode;
tail = &newNode;
}
else
{
(*tail)->next = &newNode;
tail = &newNode;
}
size++;
}
However what I find strange is that if I swap (*tail)->next = &newNode; to (*tail).next = &newNode; it still compiles. Why, and what is the correct way of doing it?

The definitions of your classes can be (for the purposes of this question) simplified into:
class List {
...
private:
Node* head;
Node* tail;
};
class Node {
...
private:
Node* next;
};
Now in your List::insert method:
Node newNode = new Node(data, NULL);
(*tail)->next = &newNode;
...when you use new expression, the result will be pointer to the newly allocated memory.
What you should do is:
Node* newNode = new Node(data, NULL);
tail->next = newNode; // <-- equivalent to (*tail).next = newNode;

Using Node->tail is short form of writing (*Node).tail. Both forms are valid. Strangeus is the fact that you say that (*Node)->tail compiles. To this happens, Node must be defined as a double pointer, i.e.:
Node **tail;
But your code has some others bugs in. In this line:
Node newNode = new Node(data, NULL);
you are define a local object and assing a dynamic memory to it. The correct way is:
Node *newNode = new Node(data, NULL); // defining it as a pointer
and instead of assing as:
head = &newNode;
do:
head = newNode;
As a final note, consider using smart pointer instead of raw pointer. The former is safer than the last

The -> operator will automatically derefference a pointer for you then call the method to the right. So:
tail->next
would also work but
tail.next
wouldn't because tail is a pointer. To use the . operator you have to defrence the pointer first as in
(*tail).next
(*tail)
turns your pointer into an object. At that point you can use either -> or .
A . will not work on a pointer but -> will.
Generally, just for easy of typing I use -> because it is shorter then using (*) to turn a pointer into an object just so I can use a dot but they are equivalent operations.

You have noticed that (*tail)->next = &newNode and (*tail).next = &newNode both compile, which strikes you as odd.
But somehow you might also have noticed that this line also compiles!
Node newNode = new Node(data, NULL);
That is the thing that you should give you pause.
You are inside of a template here. Lots of things "compile".
Did you try instantiating the template?
ADDENDUM:
Here just to show you how crazy things can be, check out this program:
#include <iostream>
using namespace std;
template <class T>
class C {
void f();
};
template <class T>
void C<T>::f() {
int x = new int;
}
int main() {
std::cout << "Hello, world\n";
}
Now check this out:
$ g++ template-example.cpp && ./a.out
Hello, world
But now notice
#include <iostream>
using namespace std;
int main() {
int x = new int;
std::cout << "Hello, world\n";
}
which yields:
$ g++ hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:4: error: invalid conversion from ‘int*’ to ‘int’
TL;DR: WHEN YOU ARE IN A TEMPLATE, THINGS THAT SHOULD NOT COMPILE SOMETIMES "DO"! (They're not really compiling -- YET!)

Related

Is it possible to implement a std::list using unique pointers?

List.h:
#pragma once
#include <iostream>
#include <memory>
#include <initializer_list>
class List{
public:
List();
List(const std::initializer_list<int> &list);
~List();
int size() const;
void push_back(int val);
void pop_back();
void pop_front();
friend std::ostream &operator << (std::ostream &os, const List &l);
private:
void printNodes() const;
struct Node {
Node(int data) : data(data) {}
std::unique_ptr<Node> next;
Node *previous;
int data;
};
int len;
std::unique_ptr<Node> head;
Node *tail;
};
List.cpp
#include "List.h"
List::List() : len(0), head(nullptr), tail(nullptr){
}
List::List(const std::initializer_list<int> &list) : len(0), head(nullptr), tail(nullptr) {
for (auto &elem : list)
push_back(elem);
}
List::~List() {
}
void List::push_back(int val){
if (tail == nullptr) {
head = std::make_unique<Node>(val);
tail = head.get();
head->next = nullptr;
head->previous = nullptr;
len++;
}
else {
tail->next = std::make_unique<Node>(val);
(tail->next)->previous = tail;
tail = tail->next.get();
tail->next = nullptr;
len++;
}
}
void List::pop_back(){
if(len == 1){
auto node = head.release();
delete node;
head = nullptr;
tail = nullptr;
}else{
// tail->previous;
}
}
void List::pop_front(){
if(len == 1){
auto node = head.release();
delete node;
head = nullptr;
tail = nullptr;
}else{
}
}
void List::printNodes() const{
Node *temp = head.get();
while (temp != nullptr) {
std::cout << temp->data << "\n";
temp = (temp->next).get();
}
}
int List::size() const{
return len;
}
std::ostream &operator<<(std::ostream & os, const List & l){
l.printNodes();
return os;
}
Source.cpp
#include <iostream>
#include "List.h"
using namespace std;
int main() {
List l{3, 5, 1, 6, 7};
cout << l << endl;
}
Hello Stack Overflow, I'm a Data structures student, and as practice, I'm trying to recreate std::list using smart pointers. Based on what I have read, it appears that unique_ptr should be the default one to use, with shared_ptr and weak_ptr only being used where unique_ptr cannot due to speed differences. Unfortunately, I have hit a wall when trying to implement pop_back() and pop_front(). Do I have to adopt shared pointers to complete the entire std::list reimplementation, or is there a way these functions can be done using unique pointers?
Yes, this is perfectly possible. Let's start with pop_back:
You have a pointer to the node already with tail, but that's not the interesting one, since it's just a raw pointer. The pointer that you need is the unique_ptr to that same node. Where is that pointer stored? Is there an easy way to get to it starting from tail?
Once you have the unique_ptr, unchaining the node from the list is as easy as resetting that pointer. Note that there is no need to call release and delete the node manually.
Now for pop_front: Here you already have the unique_ptr in hand, it's head. But you have to be careful as the whole list rests on this one. Resetting the head will make the entire list disappear. So be sure to detach the rest of the list from the head and reattach it with the list first. If you do this properly, deleting the original head will not even be a worry for you. Try it out!
Be sure to draw a picture of the list to visualize which node points where. It's rather difficult to keep all of this information in your head at once.

Why am I getting bad_alloc? Implementing a stack c++

I'm trying to implement my own Stack in C++ but I keep getting this error when I try to use the method pop() in which what I'm trying to do is:
Save element from the top in a variable called "res".
Get the reference to the next element from the node class and set it as the top.
size--
Return the variable "res".
If you could help me I'd appreciate it. Thank you!
Node class:
template<class T>
class Node {
private:
Node<T>* next;
T element;
public:
Node();
Node(const Node& orig);
~Node();
void setElement(T el);
T getElement();
Node<T>* getNext();
void setNext(Node<T>* ne);
};
Stack class:
#include "EmptyStackException.cpp"
#include "Node.cpp"
#include <iostream>
using namespace std;
template<class T>
class LinkedStack {
private:
int siz;
Node<T>* first;
public:
LinkedStack();
~LinkedStack();
int size();
bool isEmpty();
void push(T e);
T top();
T pop();
};
template<class T>
void LinkedStack<T>::push(T e) {
Node<T> node = Node<T>();
node.setNext(first);
node.setElement(e);
first = &node;
siz++;
}
template<class T>
T LinkedStack<T>::pop() {
T res = first->getElement();
first = *(first->getNext());
siz--;
}
template<class T>
void LinkedStack<T>::push(T e) {
Node<T> node = Node<T>();
node.setNext(first);
node.setElement(e);
first = &node;
siz++;
}
Since node is an object that is local to this function, as soon as this function ends, it is destroyed. However, first contains a pointer to it. So when this function returns, first contains a pointer to an object that no longer exists. You probably want this:
template<class T>
void LinkedStack<T>::push(T e) {
Node<T>* node = new Node<T>();
node->setNext(first);
node->setElement(e);
first = node;
siz++;
}
Now, node still ceases to exist when this function returns. But first doesn't contain a pointer to node, it contains the value of node -- a pointer to a dynamically allocated object.
Note that you will have to manage the lifetime of that object somehow. Ideally, you wouldn't use raw pointers so that you don't have that burden.

queue implementation with vector c++

We were instructed to implement a class that uses a vector to store a queue. I came up with the following but it's not really working. Can anyone tell me what went wrong?
The values of the numbers are correctly pushed into the vec, and the first pop() works. But if I check head->getElement(), it gives a strange number. Subsequent calls to pop() also fail.
#include <iostream>
#include <vector>
using namespace std;
template<class T>
class node{
T element;
node* next;
public:
node(): next(nullptr){};
T getElement() {return element;}
void setElement(T newElement) {element=newElement;}
node* getNext() {return next;}
void setNext(node* newNext) {next = newNext;}
};
template<class T>
class queue{
vector<node<T>> vec;
node<T>* head;
int size;
public:
queue(): head(nullptr){}
void push(node<T> newNode);
node<T> pop();
int getSize() {return unsigned(vec.size());}
vector<T> getVec()const {return vec;}
node<T>* getHead() {return head;}
void setHead(node<T>* newHead) {head = newHead;}
vector<node<T>> getVec() {return vec;}
};
int main() {
queue<int> v;
for (int i=0;i<5;i++){
node<int>* newNode = new node<int>;
newNode->setElement(i);
v.push(*newNode);
}
cout<<"The elements in the vector are initially:\n";
for (int i=0; i<v.getSize();i++)
cout<<v.getVec()[i].getElement()<<" ";
cout<<"\nAfter popping, the popped element is "<<v.pop().getElement()<<endl;
}
template<class T>
node<T> queue<T>:: pop(){
node<T>* tmp = new node<T>;
tmp->setNext(head->getNext());
head=head->getNext();
return *tmp;
}
template<class T>
void queue<T>:: push(node<T> newNode){
if (head==nullptr){
node<T>* newPtr = new node<T>;
newPtr = &newNode;
newPtr->setNext(head);
head=newPtr;
}
else{
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
node<T>* end = head;
while (end->getNext() != nullptr)
end->setNext(end->getNext());
end->setNext(newPtr);
}
vec.push_back(newNode);
}
There are many issues with your code.
First, lets fix pop. You are creating a new node tmp, setting the next and returning the same without setting the element. To fix this, you just need it to set it to head and move the head to its next.
template<class T>
node<T> queue<T>:: pop(){
node<T>* tmp = head;// = new node<T>;
//tmp->setNext(head->getNext());
head=head->getNext();
return *tmp;
}
After this you will get your element with pop. But you will get wrong element. As queue is FIFO based, you should get '0' at first pop but in your case you will not get 0. Because, your push function is also incorrect. In push, when you are pushing the first element, then you are taking the address of the node object passed which is passed by value, this leads to undefined behavior, since the node object passed would be destroyed once the function finishes. Also, in the else part of your push you are setting the next of end to its own next and hence it will go into infinite loop. Below is the corrected implementation.
template<class T>
void queue<T>:: push(node<T> newNode){
if (head==nullptr){
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
//newPtr = &newNode;
//newPtr->setNext(head);
head=newPtr;
}
else{
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
node<T>* end = head;
while (end->getNext() != nullptr)
end = end->getNext();
end->setNext(newPtr);
}
vec.push_back(newNode);
}
Lastly, there are many memory leaks in your code. You are creating a new node far more number of times than needed and also not deleting them. As, you can see now that in case of push, you just need to pass the element T and it would suffice. You don't need to pass a new node every time.
Also, try using smart pointers as it will manage a lot of things on its own.

Undeclared identifier, in a node class

I have 2 files: Node.h, Node.cpp,
In Node.h, I create the prototype for the Node class. In the prototype I create a string array 'name'. In the Node.cpp class, I tried to use a function that gives 'name' a value, but i keep getting undeclared identifier even though i identified 'name' in Node.h
node.h
#include "iostream"
#include "string.h"
#include "stdafx.h"
#include "stdio.h"
template<class T>
class Node{
char name[256];
bool useable;
public:
//Constructors
Node();
Node(const T& item, Node<T>* ptrnext = NULL);
T data;
//Access to next Node
Node<T>* nextNode();
//List modification
void insertAfter(Node<T>* p);
Node<T>* deleteAfter();
Node<T>* getNode(const T& item, Node<T>* nextptr = NULL);
//Data Retrieval
char *getName();
void *setName(char[]);
bool isUsable();
};
node.cpp
#include "Node.h"
//Default Constructor
template<class T>
Node<T>::Node(){
}
//This constructor sets the next pointer of a node and the data contained in that node
template<class T>
Node<T>::Node(const T& item,Node<T>* ptrnext){
this->data = item;
this->next = ptrnext;
}
//This method inserts a node after the current node
template<class T>
void Node<T>::insertAfter(Node<T> *p){
//Links the rest of list to the Node<T>* p
p->next = this->next;
//Links the previous node to this one
this-> next = p;
}
//This method deletes the current node from the list then returns it.
template<class T>
Node<T> * Node<T>::deleteAfter(){
Node<T>* temp = next;
if(next !=NULL){
next = next->next;
}
return temp;
}
template<class T>
Node<T> * getNode(const T& item, Node<T>* nextptr = NULL){
Node<T>* newnode; //Local pointer for new node
newNode = new Node<T>(item,nextptr);
if (newNode == NULL){
printf("Error Allocating Memory");
exit(1);
}
return newNode;
}
void setName(char input[256]){
strncpy(name,input,sizeof(name));
}
I see three things immediately wrong with the following code.
void setName(char input[256]){
strncpy(name,input,sizeof(name));
}
You did not provide the class name. This is therefore declaring a static function, and not a class member. You also forgot to do this on your getNode function.
You left out the template statement.
You put a template implementation in a cpp file. Be aware that you cannot compile the cpp file as an object -- it must be included in a header, or you can ditch the file altogether and move your implementation into your header.

C++ new pointer from pointer to pointer?

I have a template linkedList that I would like to dynamically create "head" pointers for...
I seem unable to get any syntax to work.. my best guess is:
linkedList<int>** ptr;
ptr = new (linkedList<int>*)[1];
But it doesn't work. I'm fairly new to C++ so any help is appreciated! Thanks!
To get a pointer, do:
T* ptr = new T;
where T is your type.
For a pointer-to-pointer, do:
T** ptrptr = new T*;
allocating the space for one pointer, which still needs to be filled like the first method:
*ptrptr = new T;
Now you got a valid pointer-to-pointer.
Is there some reason you are not using std::list? (or std::forward_list)
Check out the header files for std::list, or your nearest C++ book, or in fact
cppreference.com
Your linked list class template should have a function to return the head of the list. Look at std::list::begin() in your compiler's c++ library. The std::list::iterator type is a pointer to whatever goes in the list. (ie T*)
Though I'm not sure pointer array is really needed for your linked
list, as for just new construct, the following form will be compiled.
ptr = new (linkedList<int>*[1]);
EDIT:
This allocates pointer array:
linkedList<int>** ptr = new (linkedList<int>*[1]);
This allocates array:
linkedList<int>* ptr = new linkedList<int>[1];
This allocates one element:
linkedList<int>* ptr = new linkedList<int>;
Normally the head of a linked list would look something like:
node<int> *head = NULL;
When you want to create and insert a node, you'd use something like:
insert(node<int> *&list, int value) {
// insert new node containing `value` at head of `list`.
node<int> *temp = new node(value);
temp->next = list;
list=temp;
}
You could use this something like:
node<int> *list = NULL;
for (int i=0; i<10; i++)
insert(list, i);
Of course, unless this is for homework (or something on that order), you should stop working on this immediately, and just std::list (or boost::slist, if you want a singly-linked list).
Edit: I'm adding more detail mentioned by the OP in comment. For the moment, the avl_tree::insert does not attempt to maintain balance. It's just a plain-jane un-balanced insert, but it should be adequate to demonstrate what we care about at the moment.
template <class T>
struct linked_list {
node *head;
void insert(T v) {
node<T> *n = new node(v, head);
head = n;
}
linked_list() : head(NULL) {}
template <class T>
struct node {
node *next;
T data;
node(T const &v, node *n=NULL) : data(v), next(n) {}
};
};
template <class keyType, class dataType>
class avl_tree {
struct node {
node *left, *right;
char balance;
keyType key;
dataType data;
node(keyType const &k, dataType const &d)
: left(NULL), right(NULL), balance(0), key(k), data(d)
{ }
bool operator<(node const &other) {
return key < other.key;
}
} *root;
bool insert(node const *new_node, node *&tree) {
if (tree == NULL) {
tree = new_node;
return true;
}
else if (*new_node < *tree)
return insert(new_node, tree->left);
else if (*new_node > *tree)
return insert(new_node, tree->right);
else // new_node == tree
return false; // couldn't insert -- already present.
}
public:
avl_tree() : root(NULL) {}
void insert(keyType const &key, dataType const &data) {
node *temp = new node(key, data);
insert(temp, root);
}
};