Smart Pointers
When you see an int* ptr being used in your C++ code, do you need to delete it after use? If yes, should you use delete[] ptr or delete ptr? If the later code performs a delete, repeating the delete will cause a crash. If no, and no subsequent code performs the delete, it will cause a memory leak. You must have encountered the above dilemma, and smart pointers are here to solve this problem! (How wonderful)
In C++, smart pointers provide a safe and automated way of managing resources. C++11 introduced several different types of smart pointers, including std::unique_ptr, std::shared_ptr, and std::weak_ptr.
Each smart pointer has its specific use case and advantages.
Below are the usage scenarios and examples of these three types of smart pointers.
std::unique_ptr
std::unique_ptr is a smart pointer that ensures exclusive ownership of a resource, ensuring that at any given time, only one pointer owns the resource.
This prevents resource leaks and duplicate releases of resources.
Usage scenarios:
- When you want a certain object to have only one owner.
- To implement the RAII (Resource Acquisition Is Initialization) pattern.
- To avoid copying and sharing of pointers.
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>
class Resource {
public:
Resource() { std::cout << "Resource acquired : "<< this << "\n"; }
~Resource() { std::cout << "Resource destroyed : "<< this <<"\n"; }
void sayHello() const { std::cout << "Hello, Resource from : " << this <<"\n"; }
};
int main() {
std::cout << "~Enter scope" << std::endl;
{
std::unique_ptr<Resource> res1(new Resource());
res1->sayHello();
// Transfer ownership
std::unique_ptr<Resource> res2 = std::move(res1);
if (!res1) {
std::cout << "res1 is null\n";
}
res2->sayHello();
// Resource will be automatically destroyed when res2 goes out of scope
}
std::cout << "~Leave scope" << std::endl;
std::cout << "------------" << std::endl;
std::cout << "~Enter scope" << std::endl;
{
int size = 3;
std::unique_ptr<Resource[]> res1 = std::make_unique<Resource[]>(size);
for (size_t i = 0; i < size; i++)
{
res1[i].sayHello();
}
// Transfer ownership
std::unique_ptr<Resource[]> res2 = std::move(res1);
if (!res1) {
std::cout << "res1 is null\n";
}
}
std::cout << "~Leave scope" << std::endl;
return 0;
}
Automatically releases resources when going out of scope.
c++11 make_unique supports the creation of dynamic arrays
1
std::make_unique<Resource[]>(3);
std::shared_ptr
std::shared_ptr is a smart pointer that allows multiple pointers to share ownership of the same resource. The resource is automatically released when the last pointer pointing to the resource is destroyed.
Usage scenarios:
- When you need multiple owners to share the same resource.
- When the lifecycle of the resource needs to be shared among multiple objects or functions.
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
#include <iostream>
#include <memory>
class Resource {
public:
Resource() { std::cout << "Resource acquired : " << this << "\n"; }
~Resource() { std::cout << "Resource destroyed : " << this << "\n"; }
void sayHello() const { std::cout << "Hello, Resource from : " << this << "\n"; }
};
int main() {
std::shared_ptr<Resource> res1 = std::make_shared<Resource>();
std::cout << "res1.use_count : " << res1.use_count() << std::endl;
std::cout << "~Enter scope" << std::endl;
{
std::shared_ptr<Resource> res2 = res1;
res2->sayHello();
std::cout << "res1.use_count : " << res1.use_count() << std::endl;
std::cout << "res2.use_count : " << res2.use_count() << std::endl;
std::cout << "res2 goes out of scope\n";
}
std::cout << "~Leave scope" << std::endl;
std::cout << "res1.use_count : " << res1.use_count() << std::endl;
res1->sayHello();
std::cout << "res1 goes out of scope\n";
// Resource will be automatically destroyed when res1 goes out of scope
return 0;
}
use_count() can show how many shared pointers hold the resource.
When res2 goes out of scope, it releases its ownership of the resource.
In C++11, make_shared does not support the creation of dynamic arrays yet.
Creating a dynamic array will result in the following error.
1
std::shared_ptr<Resource[]> res1 = std::make_shared<Resource[]>(3);



