There are two types of smart pointers. The unique pointer is a standard method which came from C++11 implementation that returns a pointer. A unique pointer does not to be shared by other parts of the code. To use any of smart pointer you have to include the memory header file into your program.
std::unique_ptr
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
//memory file holds the code
#include <memory>
//this is a method to get a pointer
int*getPointer(intvalue){
int*p=newint{value};
returnp;
}
//method of printing
voidprintOut(int*p){
if(!p){
return;
}
std::cout<<*p<<std::endl;
}
voidmyMethod(intx){
std::unique_ptr<int>p{getPointer(x)};
//we have an object that hold the pointer
if(p==nullptr){
p.reset(newint{x});
//reset is the function which deletes
//the existing pointer memory space and
//initilizes again.
}
printOut(p.get());
//get returns actual pointer
p.reset(newint);
*p=2;
//* is overrided operator which refer
//memory location of the pointer
//like actual * operator.
printOut(p.get());
}
intmain(){
myMethod(34);
returnEXIT_SUCCESS;
}
So you may mention that t is not necessary to work about delete operation. That’s why the unique pointer overcomes our problem about memory management.
But if you copy of a unique pointer, for instance, passing to another method as a parameter, causes a problem that it deletes actual pointer. So you can’t pass a unique pointer to another method directly. Of course std::move function which calls move constructor to help us call a function. But keep it in mind, if you call a move method you can’t reach the old value of actual pointer after return the function.
But there is a solution to it. Passing reference of pointer instates of itself.
Referance of std::unique_ptr
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <memory>
voidprintOut(std::unique_ptr<int>&p){
if(!p){
return;
}
std::cout<<*p<<std::endl;
}
voidmyMethod(intx){
std::unique_ptr<int>p{newint{x}};
printOut(p);
// it uses pointer itself
std::cout<<*p<<std::endl;
// so we can reach after it
}
intmain(){
myMethod(34);
returnEXIT_SUCCESS;
On the other hand, the shared pointer is fine in many cases. Shared pointers hold an indicator counter and it increases it in every case of constructors and decreases it in each deconstruction calls. Shared pointer gives memory to the system back when there is no other copy in a complex operation.
So you don’t have to pass a pointer of the unique pointer to a method. At the same time, there is only one way, shared pointer, in the case of “has a” relation of two objects.
shared pointer
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <memory>
voidprintOut(std::shared_ptr<int>p){
if(!p){
return;
}
std::cout<<*p<<std::endl;
}
voidmyMethod(intx){
std::shared_ptr<int>p{newint{x}};
printOut(p);
std::cout<<*p<<std::endl;
}
intmain(){
myMethod(34);
returnEXIT_SUCCESS;
}
Weak Pointer
Shared pointer has two value, pointer and counter. The weak pointer indicates a pointer for the counter. And the weak pointer has two methods.
Expired is the method which returns a boolean value. If the shared pointers counter is 0 it’s expired.
The lock is the other method which returns a shared pointer of the pointer and increases the counter of it.
Weak Pointer
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <memory>
classPrinter{
std::weak_ptr<int>ptr;
public:
voidsetVal(std::weak_ptr<int>ptr){
this->ptr=ptr;
}
voiddoIt(){
if(ptr.expired()){
std::cout<<"Expired "<<std::endl;
return;
}
auto sp=ptr.lock();
std::cout<<"Value is : "<<*sp<<std::endl;
}
};
intmain(){
Printerp;
std::shared_ptr<int>mypointer{newint};
p.setVal(mypointer);
//lets set the value of 3;
*mypointer=11;
//lets check
p.doIt();
}
In circular reference, shared pointer causes a memory leak. We also use the weak pointer to avoid that.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <memory>
classA;
classB;
classA{
public:
/* shared pointer coused memory leak because it is circular
std::shared_ptr<B> b_ptr;
*/
//Avoid it
std::weak_ptr<B>b_weak_ptr;
A(){
std::cout<<"Init A"<<std::endl;
}
~A(){
std::cout<<"Distroy A"<<std::endl;
}
};
classB{
public:
/* shared pointer coused memory leak because it is circular