It is responsibility of the owner to free the memory which he is
allocated dynamically. But the question is who actually owns the memory.
Let us consider a function
char * allocate (int size)
{
char * ptr = new char[size];
return ptr;
}
here in this allocate function block of memory for characters is being allocated and the pointer to that memory location is returned. Now the question is the person who is calling this function if he doesnt store the pointer then what happens. If he stores and if he doesnt free then what happesns. In all these cases we can find memory leak.
To avoid these kind of situations in our code, its better to use the inbuilt functions provided by c++ standard library.
<memory> provides two smart pointers to help manage objects on the free store.
1. unique pointer
2. shared pointer
The most basic use of these smart pointer is to avoid memory leak.
Unique Pointer [unique_ptr]
std::unique_ptr is a smart pointer that retains ownership of an object through pointer and destroys that object when the unique_ptr goes out of scope.
Syntax :
std::unique_ptr <X> p1 (new X); // p1 is a unique_ptr of type X
Once we declare this unique_ptr, no need to think of deallocating this object. The deallocation of this object happens automatically in one of these cases.
1. unique_ptr goes out of scope
2. when you assign unique_ptr object to other unique_ptr object via assignment operator or if you use reset.
Now again if we consider same example ,
char * allocate (int size)
{
//char * ptr = new char[size];
unique_ptr <char> ptr (new char[size]);
return ptr;
}
Here in this function we are returning ptr, in this case the compiler creates a temp object and stores the value of ptr in temp object, if no one is catching that object the object will be destroyed and memory is freed. In case if we are not returning ptr here, the ptr goes out of scope when function ends and the object will be destroyed. Hence there is no possibility of memory leak here.
Shared Pointer
shared_ptr is similar to unique pointer, where are shared_ptr are copied rather than move. So the shared_ptrs share the ownership of an object , hence the object is destroyed when the last shared_ptr to that object is freed.
When we share an object, we need pointers to refer to the shared object, so the shared_ptr becomes the choice.
Most of the libraries in std, like vectors use these smart pointers for memory management, Hence there is very less or no chance of memory leak.
Unique_ptr example for creating shapes
#include <iostream>
#include <array>
#include <memory> //for unique_ptr class, for dyn alloc and dealloc of obj
#include <string>
using namespace std;
class Shape
{
public:
virtual void takeInput() = 0;
virtual void Draw() = 0;
};
class ShapeFactory;
vector <ShapeFactory *> g_factories;
class ShapeFactory
{
protected:
ShapeFactory()
{
g_factories.push_back(this);
}
public:
virtual unique_ptr<Shape> Create() = 0;
virtual string getName() = 0;
};
int main()
{
for(int i=0;i<g_factories.size();i++)
{
cout<< i+1 <<":"<<g_factories[i]->getName()<<endl;
}
int choice;
cout<<"select a shape to be drawn";
cin >>choice;
unique_ptr <Shape> pShape = g_factories[choice-1]->Create();
pShape->takeInput();
pShape->Draw();
cout<<endl<<endl;
}
//implementation
class Circle:public Shape
{
int cx,cy, radius;
void takeInput()
{
cout<<"Enter cx, cy and radius";
cin>>cx>>cy>>radius;
}
void Draw()
{
cout <<"Circle :"<<cx<<" "<<cy<<" "<<radius<<" "<<endl;
}
};
class CircleFactory : public ShapeFactory
{
unique_ptr<Shape> Create()
{
unique_ptr <Shape> c (new Circle());
return c;
}
string getName()
{
return "Circle";
}
};
CircleFactory g_cf;
class Rectangle: public Shape //used to create objects
{
int left, top ,width, height;
void takeInput()
{
cout<<"Enter left top width and height";
cin >> left >> top >> width >>height;
}
void Draw()
{
cout <<"Rectangle :"<< left <<" " << top<<" " << width <<" "<<height<<" "<<endl;
}
};
class RectangleFactory : public ShapeFactory
{
unique_ptr<Shape> Create()
{
unique_ptr <Shape> r (new Rectangle());
return r;
}
string getName()
{
return "Rectangle";
}
};
RectangleFactory g_rf;
class Triangle:public Shape
{
void takeInput()
{
cout<<"take in put trianle";
}
void Draw()
{
cout<<"trianle";
}
};
class TrianleFactory:public ShapeFactory
{
string getName(){
return "trianle";
}
unique_ptr<Shape> Create()
{
unique_ptr <Shape> t(new Triangle());
return t;
}
};
TrianleFactory g_tf;
I am not using any delete calls here even though i'm using new. But there cannot be any memory leak with this code. unique_ptr ensures that object is freed properly.
char * allocate (int size)
{
char * ptr = new char[size];
return ptr;
}
here in this allocate function block of memory for characters is being allocated and the pointer to that memory location is returned. Now the question is the person who is calling this function if he doesnt store the pointer then what happens. If he stores and if he doesnt free then what happesns. In all these cases we can find memory leak.
To avoid these kind of situations in our code, its better to use the inbuilt functions provided by c++ standard library.
<memory> provides two smart pointers to help manage objects on the free store.
1. unique pointer
2. shared pointer
The most basic use of these smart pointer is to avoid memory leak.
Unique Pointer [unique_ptr]
std::unique_ptr is a smart pointer that retains ownership of an object through pointer and destroys that object when the unique_ptr goes out of scope.
Syntax :
std::unique_ptr <X> p1 (new X); // p1 is a unique_ptr of type X
Once we declare this unique_ptr, no need to think of deallocating this object. The deallocation of this object happens automatically in one of these cases.
1. unique_ptr goes out of scope
2. when you assign unique_ptr object to other unique_ptr object via assignment operator or if you use reset.
Now again if we consider same example ,
char * allocate (int size)
{
//char * ptr = new char[size];
unique_ptr <char> ptr (new char[size]);
return ptr;
}
Here in this function we are returning ptr, in this case the compiler creates a temp object and stores the value of ptr in temp object, if no one is catching that object the object will be destroyed and memory is freed. In case if we are not returning ptr here, the ptr goes out of scope when function ends and the object will be destroyed. Hence there is no possibility of memory leak here.
Shared Pointer
shared_ptr is similar to unique pointer, where are shared_ptr are copied rather than move. So the shared_ptrs share the ownership of an object , hence the object is destroyed when the last shared_ptr to that object is freed.
When we share an object, we need pointers to refer to the shared object, so the shared_ptr becomes the choice.
Most of the libraries in std, like vectors use these smart pointers for memory management, Hence there is very less or no chance of memory leak.
Unique_ptr example for creating shapes
#include <iostream>
#include <array>
#include <memory> //for unique_ptr class, for dyn alloc and dealloc of obj
#include <string>
using namespace std;
class Shape
{
public:
virtual void takeInput() = 0;
virtual void Draw() = 0;
};
class ShapeFactory;
vector <ShapeFactory *> g_factories;
class ShapeFactory
{
protected:
ShapeFactory()
{
g_factories.push_back(this);
}
public:
virtual unique_ptr<Shape> Create() = 0;
virtual string getName() = 0;
};
int main()
{
for(int i=0;i<g_factories.size();i++)
{
cout<< i+1 <<":"<<g_factories[i]->getName()<<endl;
}
int choice;
cout<<"select a shape to be drawn";
cin >>choice;
unique_ptr <Shape> pShape = g_factories[choice-1]->Create();
pShape->takeInput();
pShape->Draw();
cout<<endl<<endl;
}
//implementation
class Circle:public Shape
{
int cx,cy, radius;
void takeInput()
{
cout<<"Enter cx, cy and radius";
cin>>cx>>cy>>radius;
}
void Draw()
{
cout <<"Circle :"<<cx<<" "<<cy<<" "<<radius<<" "<<endl;
}
};
class CircleFactory : public ShapeFactory
{
unique_ptr<Shape> Create()
{
unique_ptr <Shape> c (new Circle());
return c;
}
string getName()
{
return "Circle";
}
};
CircleFactory g_cf;
class Rectangle: public Shape //used to create objects
{
int left, top ,width, height;
void takeInput()
{
cout<<"Enter left top width and height";
cin >> left >> top >> width >>height;
}
void Draw()
{
cout <<"Rectangle :"<< left <<" " << top<<" " << width <<" "<<height<<" "<<endl;
}
};
class RectangleFactory : public ShapeFactory
{
unique_ptr<Shape> Create()
{
unique_ptr <Shape> r (new Rectangle());
return r;
}
string getName()
{
return "Rectangle";
}
};
RectangleFactory g_rf;
class Triangle:public Shape
{
void takeInput()
{
cout<<"take in put trianle";
}
void Draw()
{
cout<<"trianle";
}
};
class TrianleFactory:public ShapeFactory
{
string getName(){
return "trianle";
}
unique_ptr<Shape> Create()
{
unique_ptr <Shape> t(new Triangle());
return t;
}
};
TrianleFactory g_tf;
I am not using any delete calls here even though i'm using new. But there cannot be any memory leak with this code. unique_ptr ensures that object is freed properly.
Comments
Post a Comment