Thursday, November 14, 2019

Demonstrates how lock function is used to ensure validity of the pointer ( weak_ptr)

1) weak_ptr<> is also a smart pointer introduced in c++11, which has a reference to an object but it does not own it.
But is it referenced by a shared_ptr. So it must be converted to shared_ptr<> ,if you want to access the referenced object.

2) std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to assume temporary ownership.


3)  If the original std::shared_ptr is destroyed at this time, the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.

4) std::unique_ptr models the concept of exclusive ownership, std::shared_ptr the concept of shared ownership. If I stick to this picture then std::weak_ptr models the concept of temporary ownership because it borrows the resource from a std::shared_ptr. There is one dominant reason for having a std::weak_ptr in C++: breaking of cyclic references of std::shared_ptr's.

5) Another use for std::weak_ptr is to break reference cycles formed by objects managed . If such cycle is orphaned (i,e. there are no outside shared pointers into the cycle), the shared_ptr reference counts cannot reach zero and the memory is leaked. To prevent this, one of the pointers in the cycle can be made weak.

some example:

#include <iostream>
#include <memory>

std::weak_ptr<int> gw;

void testWeakPtr()
{
//! Use count will be 1 for the first time as it is still pointed by a shared ptr
//! But once  it is not pointed, i mean deleted, then use coint will be 0
//! so else block will be called.
//! to access, we need to convert it to shated_ptr by lock() method.
    std::cout << "use_count == " << gw.use_count() << ": ";
    if (auto spt = gw.lock()) { // Has to be copied into a shared_ptr before usage
    std::cout << *spt << "\n";
    }
    else {
        std::cout << "gw is expired\n";
    }
}

int main()
{
    {
//! shared ptr created
    auto sp = std::make_shared<int>(42);
//! Now it is refered  weak ptr
    gw = sp;
    testWeakPtr();
    }
    testWeakPtr();
    return 0;
}



Friday, November 8, 2019

Simple Queue Implementation using linked list in C++

#ifndef MYQUEUE_H
#define MYQUEUE_H


#include<iostream>
template<class T>
class MyQueue
{
private:
    struct Node
    {
        int data;
        struct Node* next=nullptr;
    };
    struct Node *front=nullptr;
    struct Node *rear=nullptr;
    struct Node *qPoint=nullptr;
public:
    struct Node* createNode();
    void insert(T e);
    struct Node* deQueue();
    void qDisplay();
    MyQueue();
};

#endif // MYQUEUE_H

template<class T>
MyQueue<T>::MyQueue()
{

}


template<class T>
typename MyQueue<T>::Node* MyQueue<T>::deQueue()
{
    if(!front){std::cout<<"Q emptry\n";return nullptr;}
 typename MyQueue<T>::Node* temp=front;
    front=front->next;
    rear=front;
    return temp;
}

template<class T>
typename MyQueue<T>::Node* MyQueue<T>::createNode()
{
 return new Node;
}
template<class T>
void MyQueue<T>::insert(T e)
{
    typename MyQueue<T>::Node*newNode=nullptr;
    try{
        newNode=createNode();
        newNode->data=e;
    }catch(const std::bad_alloc &e)
    {
        std::cout<<" Allocation Failed"<<e.what()<<"\n";
    }
    if (!front)
    {
        newNode->next=front=rear;
        qPoint=rear=front=newNode;
    }else {
        newNode->next=front;
        front=newNode;
    }
    //! to make it circular
   //! rear->next=front;

}
template<class T>
void MyQueue<T>::qDisplay()
{
    while(rear) {
    std::cout<<"Q Value= "<<rear->data<<"\n ";
    rear=rear->next;
    }
}




#include <iostream>
#include"myqueue.h"
using namespace std;

int main()
{
    MyQueue<int> mm;
    mm.insert(11);
    mm.insert(12);
    mm.insert(13);
    mm.insert(14);
    mm.insert(15);
//mm.qDisplay();
//! you can delete mode here
    std::cout<<"Q popped value ="<<mm.deQueue()->data<<std::endl;
    std::cout<<"Q popped value ="<<mm.deQueue()->data<<std::endl;
    std::cout<<"Q popped value ="<<mm.deQueue()->data<<std::endl;
    std::cout<<"Q popped value ="<<mm.deQueue()->data<<std::endl;
    std::cout<<"Q popped value ="<<mm.deQueue()->data<<std::endl;
    std::cout<<"Q popped value ="<<mm.deQueue()->data<<std::endl;
    return 0;
}

Time Complexity: Time complexity of both operations insert() and deQueue() is O(1) as we only change few pointers in both operations. There is no loop in any of the operations


Wednesday, November 6, 2019

Stack Implementation using Linklist in CPP ( Template used)

#ifndef STACK_H
#define STACK_H

template<class T>
class MyStack
{
  private:
    struct Node
    {
        T elem;
        struct Node* next;
    };
    struct Node* getNewNode(T e)const;
  struct Node* head;
public:
    void push(T elem);
    Node* pop();
    bool IsEmpty() const;
    MyStack();
};


#endif // STACK_H

#include "stack.h"
#include<iostream>
template<class T>
 MyStack<T>::MyStack()
 {
     head=nullptr;

 }
template<class T>
 void MyStack<T>::push(T elem)
 {
     typename MyStack<T>::Node* node=getNewNode(elem);
     node->next=head;
     head=node;
 }

 template<class T>
 typename MyStack<T>::Node* MyStack<T>::getNewNode(T e)const
 {
     typename MyStack<T>::Node* newNode=nullptr;
     try{
     newNode= new typename MyStack<T>::Node ;
     }catch (const std::bad_alloc& e) {
         std::cout << "Allocation failed: " << e.what() << '\n';
 }

 newNode->data=e;
 newNode->next=nullptr;
 return newNode;
 }

 template<class T>
 typename MyStack<T>::Node* MyStack<T>::pop()
 {
     if(!IsEmpty())
     {
         std::cout<<"Stack is empty\n";
     }
     else
     {
         typename MyStack<T>::Node* temp=head;
         head=head->next;
         return temp;
     }
 }
 template<class T>
    bool MyStack<T>::IsEmpty() const
    {
        return (head)?true:false;
    }
int main()
{
MyStack<int> a;
a.push(11);
a.push(12);
a.push(13);
std::cout<<"POPED Val "<<a.pop()->elem<<"\n";
std::cout<<"POPED Val "<<a.pop()->elem<<"\n";
std::cout<<"POPED Val "<<a.pop()->elem<<"\n";
std::cout<<"POPED Val "<<a.pop()->elem<<"\n";
std::cout<<"POPED Val "<<a.pop()->elem<<"\n";
}

Simple Stack Implementation

struct  stack
{
    int data;
    struct stack* next;

};

struct stack* tos=nullptr;

struct stack* getNewNode(const int d)
{
    struct stack* newNode= (struct stack* )malloc(sizeof(struct stack));
    if(!newNode)
    {
        std::cout<<"Unable to allocate memory\n";
        exit(0);
    }
newNode->data=d;
newNode->next=nullptr;
return newNode;
}

void push(struct stack** aTos, int data)
{
struct stack*node=getNewNode(data);
node->next=(*aTos);
(*aTos)=node;
}

bool stackEmpty()
{
    return (tos)?true:false;

}
struct stack* pop()
{
    if(!stackEmpty())
    {
        std::cout<<"Stack is empty\n";
        exit(0);
    }
    struct stack* temp=tos;
    tos=tos->next;
    return temp;
}