您的位置:首页 > 健康 > 养生 > 第五届中国国际进口博览会召开时间_私域电商软件的直播解决方案_怎么做百度推广的代理_企业的网络推广

第五届中国国际进口博览会召开时间_私域电商软件的直播解决方案_怎么做百度推广的代理_企业的网络推广

2024/12/23 16:27:58 来源:https://blog.csdn.net/lianyunwangqian/article/details/144087148  浏览:    关键词:第五届中国国际进口博览会召开时间_私域电商软件的直播解决方案_怎么做百度推广的代理_企业的网络推广
第五届中国国际进口博览会召开时间_私域电商软件的直播解决方案_怎么做百度推广的代理_企业的网络推广

文章目录

      • shared_ptr
      • unique_ptr
      • weak_ptr
        • 循环引用导致内存泄露
        • 使用weak_ptr修复内存泄露

shared_ptr

可共享的指针
shared_ptr中包含两个指针,一个指向具体实例对象,另一个指向控制块(contorl block),控制块中包含一个引用计数和其他一些数据。

  • shared_ptr结构

在这里插入图片描述

  • 两个shared_ptr指向同一个对象
    在这里插入图片描述
  • 初始化:
  1. 使用new pointer
std::shared_ptr<T> ptr(new T());
std::shared_ptr<T> ptr = std::make_shared<T>();
  1. 使用existing pointer
shared_ptr<T> ptr(already_existing_pointer);
shared_ptr<T> ptr = make_shared(already_existing_pointer);

example:

  std::shared_ptr<int> p1;std::shared_ptr<int> p2 (nullptr);std::shared_ptr<int> p3 (new int);std::shared_ptr<int> p4 (new int, std::default_delete<int>());std::shared_ptr<int> p5 (new int, [](int* p){delete p;}, std::allocator<int>());std::shared_ptr<int> p6 (p5);std::shared_ptr<int> p7 (std::move(p6));std::shared_ptr<int> p8 (std::unique_ptr<int>(new int));std::shared_ptr<int> foo = std::make_shared<int> (10); //same as: std::shared_ptr<int> foo (new int(10));auto baz = std::make_shared<std::pair<int,int>> (30,40);

shared_ptr相关的一些方法

MethodDescription
reset()Resets the std::shared_ptr to empty, releasing ownership of the managed object.
use_count()Returns the current reference count, indicating how many std::shared_ptr instances share ownership.
unique()Check if there is only one std::shared_ptr owning the object (reference count is 1).
get()Returns a raw pointer to the managed object. Be cautious when using this method.
swap(shr_ptr2)swaps the contents (ownership) of two std::shared_ptr instances.

Example:

#include <iostream>
#include <memory>
using namespace std;
class A
{
public:void show(){cout << "A::show()" << endl;}
};
void testSharedPtr()
{shared_ptr<A> p1 = make_shared<A>();cout << "p1 use_count: " << p1.use_count() << endl;cout << "p1 address: " << p1.get() << endl;cout << "p1 isUnique: " << p1.unique() << endl;shared_ptr<A> p2 = p1;cout << "====== execute p2 = p1 ======" << endl;cout << "p1 use_count: " << p1.use_count() << endl;cout << "p2 use_count: " << p2.use_count() << endl;cout << "p2 address: " << p2.get() << endl;cout << "p2 isUnique: " << p2.unique() << endl;p1.reset();cout << "====== execute p1.reset() ======" << endl;cout << "p1 use_count: " << p1.use_count() << endl;cout << "p2 use_count: " << p2.use_count() << endl;cout << "p1 address: " << p1.get() << endl;cout << "p2 address: " << p2.get() << endl;cout << "p1 isUnique: " << p1.unique() << endl;cout << "p2 isUnique: " << p2.unique() << endl;p1.swap(p2);cout << "====== execute p1.swap(p2) ======" << endl;cout << "p1 use_count: " << p1.use_count() << endl;cout << "p2 use_count: " << p2.use_count() << endl;cout << "p1 address: " << p1.get() << endl;cout << "p2 address: " << p2.get() << endl;cout << "p1 isUnique: " << p1.unique() << endl;cout << "p2 isUnique: " << p2.unique() << endl;
}

Result:

p1 use_count: 1
p1 address: 0000016C4EEC4BF0
p1 isUnique: 1
====== execute p2 = p1 ======
p1 use_count: 2
p2 use_count: 2
p2 address: 0000016C4EEC4BF0
p2 isUnique: 0
====== execute p1.reset() ======
p1 use_count: 0
p2 use_count: 1
p1 address: 0000000000000000
p2 address: 0000016C4EEC4BF0
p1 isUnique: 0
p2 isUnique: 1
====== execute p1.swap(p2) ======
p1 use_count: 1
p2 use_count: 0
p1 address: 0000016C4EEC4BF0
p2 address: 0000000000000000
p1 isUnique: 1
p2 isUnique: 0

unique_ptr

独占指针,只能转移所有权,不能拷贝赋值

void testUniquePtr()
{unique_ptr<A> p1(new A());cout << "p1 address: " << p1.get() << endl;unique_ptr<A> p2 = move(p1);cout << "====== execute \"p2 = move(p1)\" ======" << endl;cout << "p1 address: " << p1.get() << endl;cout << "p2 address: " << p2.get() << endl;//unique_ptr<A> p2 = p1; //compile error: can't copy unique_ptr
}

Result:

p1 address: 000001507EE7DCE0
====== execute "p2 = move(p1)" ======
p1 address: 0000000000000000
p2 address: 000001507EE7DCE0

weak_ptr

为了解决循环引用问题而引入的,weak_ptr不拥有其指向的对象,也就是说,让weak_ptr指向shared_ptr所指向对象,对象的引用计数并不会增加。

auto ptr = make_shared<string>("test");
weak_ptr<string> wp1{ ptr };
cout << "use count: " << ptr.use_count() << endl;// use count: 1

weak_ptr无法直接访问对象成员

struct Square {int size = 0;
};
auto sp = make_shared<Square>();
weak_ptr<Square> wp{ sp };
cout << wp->size << endl;   // compile-time ERROR
//通过shared_ptr访问对象成员
//weak_ptr不持有对象,也就是说weak_ptr指向的对象可能析构了,但weak_ptr却不知道。所以需要判断weak_ptr指向的对象是否还存在,有两种方式:
//1. weak_ptr的use_count()方法,判断引用计数是否为0。
//2. 调用weak_ptr的expired()方法,若对象已经被析构,则expired()将返回true。
auto sp = make_shared<Square>();
weak_ptr<Square> wp{ sp };if (!wp.expired()) 
{auto ptr = wp.lock();      // get shared_ptrcout << ptr->size << endl;
}
循环引用导致内存泄露
#include "shared_ptr.h"
#include <iostream>
#include <memory>
using namespace std;
class Son;
class Father
{
public:Father(){cout << "Father construct" << endl;}virtual ~Father(){cout << "Father destruct" << endl;}shared_ptr<Son> son;
};class Son
{
public:Son(){cout << "Son construct" << endl;}virtual ~Son(){cout << "Son destruct" << endl;}shared_ptr<Father> father;
};void testWeakPtr()
{shared_ptr<Father> pFather = make_shared<Father>();cout << "pFather use_count: " << pFather.use_count() << endl;shared_ptr<Son> pSon = make_shared<Son>();cout << "pSon use_count: " << pSon.use_count() << endl;pFather->son = pSon;cout << "====== execute \"pFather->son = pSon\" ======" << endl;cout << "pFather use_count: " << pFather.use_count() << endl;cout << "pSon use_count: " << pSon.use_count() << endl;pSon->father = pFather;cout << "====== execute \"pSon->father = pFather\" ======" << endl;cout << "pFather use_count: " << pFather.use_count() << endl;cout << "pSon use_count: " << pSon.use_count() << endl;cout << "==========" << endl;
}

Result:

Father construct
pFather use_count: 1
Son construct
pSon use_count: 1
====== execute "pFather->son = pSon" ======
pFather use_count: 1
pSon use_count: 2
====== execute "pSon->father = pFather" ======
pFather use_count: 2
pSon use_count: 2
==========

分析:
main函数退出之前,Father和Son对象的引用计数都是2。
son指针销毁,这时Son对象的引用计数是1。
father指针销毁,这时Father对象的引用计数是1。
由于Father对象和Son对象的引用计数都是1,这两个对象都不会被销毁,从而发生内存泄露。

使用weak_ptr修复内存泄露
#include "shared_ptr.h"
#include <iostream>
#include <memory>
using namespace std;
class Son;
class Father
{
public:Father(){cout << "Father construct" << endl;}virtual ~Father(){cout << "Father destruct" << endl;}shared_ptr<Son> son;
};class Son
{
public:Son(){cout << "Son construct" << endl;}virtual ~Son(){cout << "Son destruct" << endl;}weak_ptr<Father> father;
};void testWeakPtr()
{shared_ptr<Father> pFather = make_shared<Father>();cout << "pFather use_count: " << pFather.use_count() << endl;shared_ptr<Son> pSon = make_shared<Son>();cout << "pSon use_count: " << pSon.use_count() << endl;pFather->son = pSon;cout << "====== execute \"pFather->son = pSon\" ======" << endl;cout << "pFather use_count: " << pFather.use_count() << endl;cout << "pSon use_count: " << pSon.use_count() << endl;pSon->father = pFather;cout << "====== execute \"pSon->father = pFather\" ======" << endl;cout << "pFather use_count: " << pFather.use_count() << endl;cout << "pSon use_count: " << pSon.use_count() << endl;cout << "==========" << endl;
}

Result:

Father construct
pFather use_count: 1
Son construct
pSon use_count: 1
====== execute "pFather->son = pSon" ======
pFather use_count: 1
pSon use_count: 2
====== execute "pSon->father = pFather" ======
pFather use_count: 1
pSon use_count: 2
==========
Father destruct
Son destruct

分析:
main函数退出前,Son对象的引用计数是2,而Father的引用计数是1。
son指针销毁,Son对象的引用计数变成1。
father指针销毁,Father对象的引用计数变成0,导致Father对象析构,Father对象的析构会导致它包含的son_指针被销毁,这时Son对象的引用计数变成0,所以Son对象也会被析构。

Reference:
https://www.geeksforgeeks.org/shared_ptr-in-cpp/
https://cplusplus.com/reference/memory/shared_ptr/shared_ptr/
https://www.geeksforgeeks.org/auto_ptr-unique_ptr-shared_ptr-weak_ptr-in-cpp/
谈谈 shared_ptr 的那些坑

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com