当前位置:网站首页>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 .=.=
边栏推荐
- 榕树贷款C语言结构体里的成员数组和指针
- Introduction to redis
- Quick sequencing and optimization
- Deployment of ruoyi's environment and operation of the system
- 常见弱口令大全
- MySQL underlying data structure
- What are "full five unique" and "full two unique"? Any difference?
- redis入门练习
- Insert pictures and videos in typera
- MySQL Chinese failure
猜你喜欢

unity之二维数组实现正六边形地图

The application and significance of digital twins are the main role and conceptual value of electric power.

JMeter distributed pressure measurement

Vector to SVG method

Characteristics and determination scheme of Worthington pectinase

477-82(236、61、47、74、240、93)

Introduction to database - Introduction to database

Learning and understanding of four special data types of redis

mysql底层数据结构

The diagram of user login verification process is well written!
随机推荐
Explain详解
复盘:图像有哪些基本属性?关于图像的知识你知道哪些?图像的参数有哪些
Number of square arrays (day 81)
客户端发送一条sql如何与服务器交互
快速排序及优化
Characteristics and experimental suggestions of abbkine abfluor 488 cell apoptosis detection kit
[understanding of opportunity -52]: the depth of communication varies from person to person
[common search questions] 111
Characteristics and determination scheme of Worthington pectinase
Detailed explanation of const usage in C language
Spark Learning Notes (VI) -- spark core core programming RDD action operator
unity之二维数组实现正六边形地图
Deployment of ruoyi's environment and operation of the system
Typescript TS basic knowledge interface, generics
Number of 0 at the end of factorial
【树链剖分】2022杭电多校2 1001 Static Query on Tree
MySQL underlying data structure
Permutation and binary (Ji, DA) (day 84)
关于使用hyperbeach出现/bin/sh: 1: packr2: not found的解决方案
C语言力扣第43题之字符串相乘。优化竖式