In: Computer Science
c++
Add exception handling to the MyStack class (e.g. an instance of the class should throw an exception if an attempt is made to remove a value from an empty stack) and use the MyStack class to measure the execution cost of throwing an exception. Create an empty stack and, within a loop, repeatedly execute the following try block:
try { i n t s t a c k . pop ( ) ;
} catch ( e x c e p ti o n& e ) { . . . }
Compare the execution time to the simpler statement that avoids the exception altogether.
i f ( ! i n t s t a c k . i s em p t y ( ) )
i n t s t a c k . pop ( ) ;
Here is the completed code for this problem. Comments are included, go through it, learn how things work and let me know if you have any doubts or if you need anything to change. If you are satisfied with the solution, please rate the answer. Thanks
//updated MyStack.hpp
#ifndef MyStack_H
#define MyStack_H
#include<vector>
#include<stdexcept>
template <typename T>
class MyStack{
private:
//using a vector as underlying data structure
std::vector<T> stk;
public:
//adds an element to the top (back)
void push(T element);
//removes and returns the top element
T pop();
//returns the top element, without removing
T top() const;
//returns true if stack is empty
bool empty() const;
//returns the current number of elements
int size() const;
};
//implementation of all methods
template <typename T>
void MyStack<T>::push(T element){
//simply adding to the back
stk.push_back(element);
}
template <typename T>
T MyStack<T>::pop(){
//throwing exception if stack is empty
if(empty()){
throw std::runtime_error("empty stack!");
}
//getting last element
T element=stk[stk.size()-1];
//removing it
stk.pop_back();
//returning it
return element;
}
template <typename T>
T MyStack<T>::top() const{
//throwing exception if stack is empty
if(empty()){
throw std::runtime_error("empty stack!");
}
//getting and returning last element
T element=stk[stk.size()-1];
return element;
}
template <typename T>
bool MyStack<T>::empty() const{
return stk.empty();
}
template <typename T>
int MyStack<T>::size() const{
return stk.size();
}
#endif
//main.cpp (for comparing execution times)
#include <iostream>
#include<chrono>
#include "MyStack.hpp"
using namespace std;
using namespace std::chrono;
int main()
{
//creating an empty stack
MyStack<int> intstack;
int loopCount=1000000;
//recording start time
auto start1 = high_resolution_clock::now();
//looping for loopCount number of times
for(int i=0;i<loopCount;i++){
//popping from stack, catching exception
try { intstack.pop() ;
}
catch ( exception& e) { }
}
//recording end time, and finding time difference in micro seconds
auto stop1 = high_resolution_clock::now();
auto time1 = duration_cast<microseconds>(stop1 - start1);
//displaying result
cout<<"Using try catch took "<<time1.count()<<" micro seconds to run a loop of "<<
loopCount<<" times"<<endl;
//recording start time
auto start2 = high_resolution_clock::now();
//looping
for(int i=0;i<loopCount;i++){
//checking if stack is empty before popping
if(!intstack.empty()){
intstack.pop();
}
}
//recording end time and finding time taken
auto stop2 = high_resolution_clock::now();
auto time2 = duration_cast<microseconds>(stop2 - start2);
//displaying result
cout<<"Using statements avoiding excepions took "<<time2.count()<<
" micro seconds to run a loop of "<< loopCount<<" times"<<endl;
//Obviously, the second option is way faster than using try-catch
return 0;
}
/*OUTPUT*/
Using try catch took 5020278 micro seconds to run a loop of 1000000 times
Using statements avoiding excepions took 38256 micro seconds to run a loop of 1000000 times