当前位置:网站首页>Smart pointer shared_ ptr、unique_ ptr、weak_ ptr
Smart pointer shared_ ptr、unique_ ptr、weak_ ptr
2022-07-27 03:43:00 【Aries_ Ro】
Intelligent pointer
Problems solved by smart pointers
Intelligent pointer It mainly solves the following two problems :
- avoid Memory leak . It is generally used malloc、new Allocating memory on the heap requires free、delete Hand release ; Using smart pointers can automatically free memory .
- share Propagation and release of ownership pointer , For example, in a multithreaded project, you can deal with the problem of the same object destruction of different threads .
Smart pointer classification
C++98 There is a smart pointer auto_ptr( At present, it has been abandoned ),C++11 Yes 3 A commonly used pointer shared_ptr,unique_ptr,weak_ptr.
- shared_ptr: share Ownership of objects , Slightly poor performance .
- unique_ptr: Monopoly Ownership of objects , Because there is no reference count , The performance is better than shared_ptr.
- weak_ptr: This smart pointer is usually used to match shared_ptr, solve Circular reference The problem of .
shared_ptr
Memory model diagram

- shared_ptr It's a Template class .
- shared_ptr Internal Two pointers , One ptr Point to object , One ptr Point to the control block . The control block contains the reference count (reference count, Or call it use_count) And a weak count (weak_count, Generally in weak_ptr Only with the cooperation of ).
shared_ptr Example
// Ordinary memory allocation
Buffer buf = new Buffer("auto free memory");
delete buf;// Need to cooperate with delete Use
// The smart pointer points to the object that allocates memory
shared_ptr<buffer> buf = make_shared<Buffer>("auto free memory");
// Outside the scope of action , Automatically free up memory
shared_ptr meaning
shared_ptr Use reference counting to record objects Number of citations . every last shared_ptr Copies of point to the same memory , When the last one shared_ptr Deconstruction time , That is to say use_count by 0 after , Memory will be released .
shared_ptr Basic usage and common functions
Common functions
- s.get(): return shared_ptr Naked pointer saved in .
- s.reset(…): Reset shared_ptr, Put the pointer s Release and empty , The reference count is subtracted by one . If reset With input parameters ( An object ), Then the pointer is released and re pointed to the object , The reference count corresponding to the original object is minus one .
- s.use_count(): return shared_ptr Reference count of .
- s.unique(): If use_count by 1, Then return to true, No return false.
Construction of smart pointer , initialization
Generally preferred make_shared To construct smart pointers , More efficient .
auto sp1 = make_shared<int>(100);
// perhaps
shared_ptr<int> sp1 = make_shared<int>(100);
The following methods can also be initialized shared_ptr, But the efficiency is not as good as make_shared
std::shared_ptr<int> p1(new int(1));
std::shared_ptr<int> p2 = p1;
std::shared_ptr<int> p3;
p3.reset(new int(1));
Reasons for different efficiency : because shared_ptr The constructor will perform memory allocation twice , One time int object , Count references at once . and make_shared Memory allocation will only be performed once , Allocate the two data at one time .
shared_ptr Yes, there is explicit Definition Of , Therefore, you cannot assign a raw pointer directly to a smart pointer , The following operation is wrong :
std::shared_ptr<int> p = new int(1);// This operation implicitly calls the copy constructor , dissatisfaction explicit Definition
Get the original pointer get
When the original pointer needs to be obtained , Can pass get Method to return the original pointer , The code is as follows :
std::shared_ptr<int> ptr(new int(1));
int *p = ptr.get(); //
// Incaution delete p, Will cause this memory delete two
Use caution p.get() The return value of .p.get() The return value of is equivalent to the value of a bare pointer , Use this value inappropriately , All errors in the above traps can occur . as follows :
- Don't save p.get() The return value of , Whether saved as a bare pointer or shared_ptr It's all wrong
- Saved as a bare pointer, I don't know when it will become a dangling pointer , Save as shared_ptr An independent pointer is generated
- Don't delete p.get() The return value of , Will result in a block of memory delete Two mistakes
Specify the delete
shared_ptr You can specify a delegator .
The sample code is as follows :
#include <iostream>
#include <memory>
using namespace std;
void DeleteIntPtr(int *p) {
cout << "call DeleteIntPtr" << endl;
delete p;
}
int main()
{
std::shared_ptr<int> p(new int(1), DeleteIntPtr);
return 0;
}
Delete dynamic array
because shared_ptr Array objects are not supported by the default eliminator of , So when used shared_ptr management The dynamic array when , At this time, the designated delegator plays a big role .
The code is as follows :
#include <iostream>
#include <memory>
using namespace std;
void DeleteIntPtr(int *p) {
cout << "call DeleteIntPtr" << endl;
delete p;
}
int main()
{
std::shared_ptr<int> p3(new int[10], [](int *p) {
delete [] p;});// The specified delegator is an anonymous function lambda Expression rendering
return 0;
}
shared_ptr What should we pay attention to
1. A primitive pointer initializes Multiple shared_ptr, Can cause Second release Same memory space .
int *ptr = new int;
shared_ptr<int> p1(ptr);
shared_ptr<int> p2(ptr); // error
because p1,p2 There is no correlation between the two pointers ,( The strong reference count for each pointer is 1), So it's releasing ptr The memory pointed to ,p1 and p2 Will be released This memory space , There is obviously a problem ( A memory space is freed twice ).
2. Don't create... In function arguments shared_ptr.
as follows :
function(shared_ptr<int>(new int), g()); // defective
because C++ The calculation order of function parameters of may be different under different conventions of different compilers , Usually from right to left , But it can also be left to right , therefore , The possible process is to new int, And then call g(), If it happens g() Something goes wrong , and shared_ptr Not yet created , be int Memory leaks , The correct way to write it is to create a smart pointer first , The code is as follows :
shared_ptr<int> p(new int);
function(p, g());
3. Avoid circular references .
#include <iostream>
#include <memory>
using namespace std;
class A {
public:
std::shared_ptr<B> bptr;
~A() {
cout << "A is deleted" << endl;
}
};
class B {
public:
std::shared_ptr<A> aptr;
~B() {
cout << "B is deleted" << endl;
}
};
int main()
{
{
// Set a scope
std::shared_ptr<A> ap(new A);
std::shared_ptr<B> bp(new B);
ap->bptr = bp;
bp->aptr = ap;
}
cout<< "main leave" << endl; // Circular reference causes ap bp Exited the scope without destructions
return 0;
}
Circular reference causes ap and bp The reference count is 2, After leaving the scope ,ap and bp The reference count for is decremented to 1, Instead of reducing to 0, As a result, neither pointer will be destructed , There is a memory leak .
The solution is to put A and B Change any member variable to weak_ptr
such as :
class A {
public:
std::weak_ptr<B> bptr; // It is amended as follows weak_ptr
~A() {
cout << "A is deleted" << endl;
}
};
unique_ptr
unique_ptr meaning
- unique_ptr Is an exclusive smart pointer , You can't put a unique_ptr The object pointed to is assigned to another unique_ptr
- unique_ptr Can point to an array
- unique_ptr You need to determine the type of delegator
unique_ptr<T> my_ptr(new T);
unique_ptr<T> my_other_ptr = my_ptr; // Report errors , Can't copy
move Transfer
unique_ptr Reproduction is not allowed , but You can transfer ownership to others through functions unique_ptr, adopt std::move To move to other unique_ptr, In this way, it no longer owns the ownership of the original pointer . for example
unique_ptr<T> my_ptr(new T); // correct
unique_ptr<T> my_other_ptr = std::move(my_ptr); // correct
make_unique
make_unique Is in c++14 Added to the standard library .
std::make_unique upw1(std::make_unique<Widget>());
// perhaps
std::unique_ptr<Widget> upw2(new Widget);
unique_ptr and shared_ptr contrast
1.unique_ptr Can point to an array , as follows :
std::unique_ptr<int []> ptr1(new int[10]);
ptr1[9] = 9;
std::shared_ptr<int []> ptr2(new int[10]); // This is illegal
std::shared_ptr<int> ptr3(new int[10]);// This is legal
2.unique_ptr Specify the delegator and shared_ptr There's a difference ,unique_ptr You need to determine the type of delegator , Can not be like shared_ptr In that way, directly specify the delegator .
std::shared_ptr<int> ptr3(new int(1), [](int *p){
delete p;}); // correct
std::unique_ptr<int, void(*)(int*)> ptr5(new int(1), [](int *p){
delete p;}); // correct
shared_ptr and unique_ptr Use scenarios
If you want only one smart pointer to manage resources or arrays, use unique_ptr, If you want multiple smart pointers to manage the same resource, use shared_ptr.
weak_ptr
- When two objects use one for each other shared_ptr Member variables point to each other , Causes circular references , Invalidate reference count , This leads to memory leaks .
- weak_ptr Is an intelligent pointer that does not control the life cycle of an object , It points to a shared_ptr The object of Management . The memory management of this object is the strong reference shared_ptr, weak_ptr It just provides an access to the managed objects .
- weak_ptr The purpose of the design is to match shared_ptr The introduction of a smart pointer to assist shared_ptr Work , It can only come from one shared_ptr Or another weak_ptr Object construction , Its construction and destructions do not increase or decrease the reference count .
#include <iostream>
#include <memory>
using namespace std;
class A {
public:
std::weak_ptr<B> bptr; // It is amended as follows weak_ptr
~A() {
cout << "A is deleted" << endl;
}
};
class B {
public:
std::shared_ptr<A> aptr;
~B() {
cout << "B is deleted" << endl;
}
};
int main()
{
{
// Set a scope
std::shared_ptr<A> ap(new A);
std::shared_ptr<B> bp(new B);
ap->bptr = bp;
bp->aptr = ap;
}
cout<< "main leave" << endl;
return 0;
}
Thread safety of smart pointer
shared_ptr The interior of is encapsulated with a lock , Because smart pointers to the same object The reference count pointer points to the same resource . Actually, the reference count is shared_ptr The bottom layer is implemented in the form of pointers , All objects access the same space through pointers , In order to share . All smart pointers are on When the reference count is added or subtracted, there is “ Lock ” and “ Release the lock ” The operation of .
Conclusion :shared_ptr Thread safe when counting references to ( Because it's atomic manipulation ).
and shared_ptr Managing objects is not necessarily thread safe .
When different threads , Manipulation The same shared_ptr Intelligent pointer when , Thread insecurity can occur .
Because managing objects with smart pointers requires two steps , First, a pointer points to the managed object , Then a pointer controls the reference count .
If the first step of the pointer is completed , Before the second step begins CPU occupied , Thread safety problems will occur when another thread also operates this smart pointer .
Different threads , operation Different shared_ptr Intelligent pointer Thread safe .=.=
边栏推荐
- Introduction to database - Introduction to database
- Tool class of localdatetime sorted out by yourself
- Redis spike case, learn from Shang Silicon Valley teacher in station B
- How to conduct 360 assessment
- 数字孪生实际应用:智慧城市项目建设解决方案
- Double disk: the main differences between DFS and BFS, the differences in ideology, and the differences in code implementation
- Data analysis and disassembly method of banyan tree in Bairong
- Textbox in easyUI inserts content at the cursor position
- Duplicate disc: what are the basic attributes of an image? What do you know about images? What are the parameters of the image
- 数据库概论 - MySQL的简单介绍
猜你喜欢

Message rejected MQ

Number of 0 at the end of factorial

基于OpenCV的轮廓检测(2)

快速排序及优化

一种分布式深度学习编程新范式:Global Tensor

Network security / penetration testing tool awvs14.9 download / tutorial / installation tutorial

mysql底层数据结构

Deeply understand the underlying data structure and algorithm of MySQL index

客户端发送一条sql如何与服务器交互

Introduction to database - Introduction to database
随机推荐
Deeply understand the underlying data structure and algorithm of MySQL index
在typora中插入图片和视频
mysql底层数据结构
若依框架代码生成详解
MySQL的数据库有关操作
GetObject call timing of factorybean
【树链剖分】模板题
MySQL Chinese failure
Textbox in easyUI inserts content at the cursor position
Code review pyramid
flask_ Reqparse parser inheritance in restful
基于OpenCV的轮廓检测(1)
Introduction to redis
477-82(236、61、47、74、240、93)
mysql出现不存在错误
【1206. 设计跳表】
LPCI-252通用型PCI接口CAN卡的功能和应用介绍
百融榕树数据分析拆解方法
How many implementation postures of delay queue? Daily essential skills!
30 minutes to thoroughly understand the synchronized lock upgrade process