当前位置: 首页 > wzjs >正文

庄河网站建设公司国外的素材网站

庄河网站建设公司,国外的素材网站,天眼查公司注册信息,wix网站建设文章目录 unique_ptr所有权转移所有权释放make_unique 和直接(new)unique_ptr区别一 :需要一次性处理多个资源分配的地方make_unique比unique_ptr更安全区别二 :直接new支持自定义删除器 shared_ptrshared_ptr智能指针指向同一个对…

文章目录

  • unique_ptr
    • 所有权转移
    • 所有权释放
    • make_unique 和直接(new)unique_ptr
      • 区别一 :需要一次性处理多个资源分配的地方make_unique比unique_ptr更安全
      • 区别二 :直接new支持自定义删除器
  • shared_ptr
    • shared_ptr智能指针指向同一个对象的不同成员
    • 循环引用问题
    • 为什么weak_ptr能解决shared_ptr的循环引用问题
    • make_shared 和 直接 new 一个shared_ptr的区别
      • 区别一:make_shared资源分配更安全
      • 区别二:直接new支持自定义删除器
      • 区别三:内存分配方式不同
      • 为什么make_unique和直接new unique_ptr都是一次分配内存
      • shared_ptr合并分配的缺点
        • shared_ptr控制块内存的延迟释放是内存泄漏吗?

unique_ptr

所有权转移

unique_ptr不能被拷贝和用于赋值,因为unique_ptr删掉了这两个函数
在这里插入图片描述
但是底层源码重载了传右值的拷贝构造
所以可以通过std::move来通过转移所有权

unique_ptr<Data> p6(new Data());
//不可复制构造和赋值复制
//unique_ptr<Data>p7 = p6; 错误//p6释放所有权 转移到p7
unique_ptr<Data>p7 = move(p6);unique_ptr<Data>p8(new Data());
p7 = move(p8);//重新移动赋值,原有的p6会被释放掉
//重置空间,原空间清理
p7.reset(new Data());

所有权释放

注意!当unique_ptr释放所有权以后智能指针就不会再管理这块空间,需要自己手动释放空间!

//释放所有权
unique_ptr<Data>p9(new Data());
auto ptr9 = p9.release();//注意,release释放所有权以后要自己清理空间
delete ptr9;//!!!!!!

make_unique 和直接(new)unique_ptr

区别一 :需要一次性处理多个资源分配的地方make_unique比unique_ptr更安全

void process_data(std::unique_ptr<Data> p1, std::unique_ptr<Data> p2
);process_data(std::unique_ptr<Data>(new Data("A")),  // 分配资源 Astd::unique_ptr<Data>(new Data("B"))   // 分配资源 B
);

编译器在构造函数参数时,​执行顺序是不确定的。可能的执行顺序例如:

  1. new Data(“A”) → 成功,得到一个裸指针 A
  2. new Data(“B”) → 成功,得到一个裸指针 B*
  3. 构造unique_ptr 接管 A*
  4. 构造 unique_ptr 接管 B*

如果中间发生异常:

  1. new Data(“A”) → 成功,得到 A*
  2. new Data(“B”) → ​抛出异常(例如内存不足)​ ​此时 A* 尚未被 unique_ptr 接管!​ 异常被抛出后,裸指针 A* 无法被自动释放 → ​内存泄漏。

如果选用make_unique

process_data(std::make_unique<Data>("A"),  // 直接构造并接管资源 Astd::make_unique<Data>("B")   // 直接构造并接管资源 B
);

此时每一步的执行:

  1. make_unique(“A”) → ​立即构造对象并封装到 unique_ptr,无裸指针暴露
  2. make_unique(“B”) → 同上 如果 make_unique(“B”) 抛出异常:
    make_unique(“A”) 已经返回的 unique_ptr 会正常析构 → 资源 A 被自动释放没有泄漏!

区别二 :直接new支持自定义删除器

new支持在构造 unique_ptr 时指定自定义删除器

std::unique_ptr<MyClass, Deleter> p(new MyClass, custom_deleter);

但是make_unique不支持,只能使用默认的 delete 操作符。

shared_ptr

shared_ptr智能指针指向同一个对象的不同成员

sc2和sc3 分别 指向sc1的index1成员和index2成员,使sc1的引用计数+2

class Data
{
public:Data() {cout<< "Begin Data" << endl;}~Data() { cout<< "End Data" << endl; }int index1 = 0;int index2 = 0;
};{shared_ptr<Data>sc1(new Data);//打印引用计数 = 1cout << "sc1.use_count() = " << sc1.use_count() << endl;shared_ptr<int>sc2(sc1,&sc1->index1);//引用计数+1shared_ptr<int>sc3(sc1, &sc1->index2);//引用计数+1//打印引用计数 = 3cout << "sc1.use_count() = " << sc1.use_count() << endl;
}

在这里插入图片描述

循环引用问题

当两个或多个对象通过 shared_ptr ​互相持有对方时,它们的引用计数永远不会归零,导致内存无法释放。

	class A{public:A() { cout << "Create A" << endl; }~A() { cout << " Drop A " << endl; }void Do(){cout << "Do b2.use_count() = " << b2.use_count() << endl;auto b = b2.lock(); //复制一个shared_ptr 引用计数加一cout << "Do b2.use_count() = " << b2.use_count() << endl;}shared_ptr<B> b1;//强智能指针weak_ptr<B> b2;  //弱智能指针};class B{public:B() { cout << "Create B" << endl; }~B(){ cout << " Drop B " << endl; }shared_ptr<A> a1;//强智能指针weak_ptr<A> a2;  //弱智能指针};{auto a = make_shared<A>();//a引用计数+1auto b = make_shared<B>();//b引用计数+1a->b1 = b;//b引用计数+1//出作用域前,引用计数为2cout << "a->b1 = b;b.use_count()=" << b.use_count() << endl;b->a1 = a;//a引用计数+1//出作用域前,引用计数为2cout << "b->a1 = a;a.use_count()=" << a.use_count() << endl;}

由于调用问题,导致出作用域以后a和b的引用计数都还是1,所以空间没有被释放

在这里插入图片描述

改成使用weak_ptr

	{auto a = make_shared<A>();auto b = make_shared<B>();a->b2 = b;//weak_ptr 引用计数不加一a->Do();//Do函数里引用计数加一,出Do函数作用域减一cout << "a->b2 = b;b.use_count()=" << b.use_count() << endl;b->a2 = a;//引用计数不加一cout << "b->a2 = a;a.use_count()=" << a.use_count() << endl;}//不会产生循环引用问题

为什么weak_ptr能解决shared_ptr的循环引用问题

weak_ptr 本身不拥有资源所有权
它只是观察 shared_ptr 管理的对象,不会增加引用计数。

所以a->b2 = b;这句不会增加b的引用计数
同理b->a2 = a;这句也不会增加a的引用计数

但是由于weak_ptr只是一个观察者,无法访问任何资源,仅“观察”资源,不拥有所有权如果想要访问资源该怎么办呢?

如同a->Do();里做的那样
只要原 shared_ptr(即 a)未释放资源,就可以通过 lock() 获取有效的 shared_ptr 并访问。

void Do()
{cout << "Do b2.use_count() = " << b2.use_count() << endl;auto b = b2.lock(); //返回一个shared_ptr 引用计数加一//这里还可以做其他的访问shared_ptr资源的操作cout << "Do b2.use_count() = " << b2.use_count() << endl;}//出作用域加上的那个引用计数自动-1

通过weak_ptr.lock()返回 一个 shared_ptr 并将引用计数加一

(注意!只有当原shared_ptr对象还存在的时候才会返回shared_ptr,否者返回nullptr)

除了放函数里,还能放判断条件里

    if (auto a_shared = b->a_weak.lock()) {// 返回nullptr 说明shared_ptr被释放//不会执行此处} else {//引用计数+1std::cout << "A is already destroyed!" << std::endl;  // 输出此句}//引用计数-1

通过这种方式,weak_ptr 可以安全地观察资源,而不会导致循环引用或内存泄漏

make_shared 和 直接 new 一个shared_ptr的区别

区别一:make_shared资源分配更安全

原因和make_unique一样,这里就不再赘述了

区别二:直接new支持自定义删除器

区别三:内存分配方式不同

由于shared_ptr除了维护对象本身的内存以外还要维护一个控制块

  • ​强引用计数​(use_count):记录有多少个 shared_ptr 共享对象
  • ​弱引用计数​(weak_count):记录有多少个weak_ptr 观察对象
  • 自定义删除器​(如果存在)。 ​
  • 对象指针​(指向实际分配的对象)。

make_shared 在底层会 ​一次性分配一块连续内存,既存储对象本身,也存储控制块。

但是new shared_ptr会有两次分配

std::shared_ptr<MyClass> p(new MyClass);
  1. 第一次分配:new MyClass 分配对象内存。
  2. ​第二次分配:shared_ptr 构造函数内部为控制块分配内存。

为什么make_unique和直接new unique_ptr都是一次分配内存

因为unique_ptr 不需要维护引用计数,因此 ​没有控制块。无论通过 make_unique 还是直接 new,都只需分配对象内存

shared_ptr合并分配的缺点

对象和控制块内存绑定,即使所有 shared_ptr 销毁,若仍有 weak_ptr 存在,对象内存仍然需等待控制块释放(但析构函数会被及时调用)

shared_ptr控制块内存的延迟释放是内存泄漏吗?

由于make_shared 是一次性分配一块连续内存,同时存储 ​对象实例 和 ​控制块​(包含引用计数、弱引用计数等)

所以当没有weak_ptr存在时

通过make_shared建立的shared_ptr:

  • 对象析构函数立即被调用。
  • 整块内存(对象 + 控制块)立即释放。

通过new建立的shared_ptr:

  • 对象内存立即释放。
  • 控制块内存也立即释放。

当有weak_ptr存在时

通过make_shared建立的shared_ptr:

  • 对象析构函数被调用(资源清理)。 ​
  • 对象内存和控制块内存暂时保留​(直到所有 weak_ptr 也被销毁)。

通过new建立的shared_ptr:

  • 对象内存立即释放(仅保留控制块内存)。

由于make_shared对象和控制块内存是连续的,无法单独释放对象内存。所以必须等待所有 weak_ptr 销毁后,​整块内存才能一起释放。

那这是内存泄漏吗?

不是!​ 内存泄漏的定义是:​无法再访问且未释放的内存。
而在此时:
对象析构函数已被调用(资源已清理)。
内存仍被 weak_ptr 的控制块管理,虽然未释放,但程序仍能通过 weak_ptr 的机制感知到内存状态。
当所有 weak_ptr 销毁后,内存会被正确释放。


文章转载自:

http://61kDyXvt.hnhkz.cn
http://QMOBSA69.hnhkz.cn
http://mq0hMkQo.hnhkz.cn
http://JVo8glS5.hnhkz.cn
http://Vn8955Iq.hnhkz.cn
http://rDEBNJ6B.hnhkz.cn
http://yQQhoNpO.hnhkz.cn
http://whMqbVMM.hnhkz.cn
http://p2REDQSe.hnhkz.cn
http://TB0iJOWd.hnhkz.cn
http://YbRB4hhf.hnhkz.cn
http://zYrRpBab.hnhkz.cn
http://4F1osFRv.hnhkz.cn
http://7L2N7nCW.hnhkz.cn
http://yiqbGb7u.hnhkz.cn
http://15BNspwR.hnhkz.cn
http://OpnXEe9g.hnhkz.cn
http://VtOlh36J.hnhkz.cn
http://q3GBVGqX.hnhkz.cn
http://zkg07nXV.hnhkz.cn
http://6KV6lnrO.hnhkz.cn
http://7CwMiU8C.hnhkz.cn
http://u1nYYfuL.hnhkz.cn
http://4ksDmgkm.hnhkz.cn
http://kISBrLmc.hnhkz.cn
http://T354SM5O.hnhkz.cn
http://iufzBaqt.hnhkz.cn
http://PNgc5zuX.hnhkz.cn
http://vRrxXOK2.hnhkz.cn
http://60z0XXGt.hnhkz.cn
http://www.dtcms.com/wzjs/778465.html

相关文章:

  • wordpress站内优化贝壳找房网站做销售
  • 河北省住房和城身建设厅网站惠州建设银行网站
  • 昆明网站建设电话做全国家电维修网站到哪里做
  • 宜春网站开发公司电话wordpress单栏简洁
  • 法与家国建设征文网站网站模板怎么用法
  • 网站正在建设中模板 htmlwordpress下载主题footer
  • 福州交通建设投资集团网站wordpress漂亮主题
  • 莆田网站制作报价沈阳做人流哪个医院好安全
  • 宽带收费价格在线排名优化
  • 网站开发与设计岗位职责wordpress 瀑布流
  • 免费1级做爰片在线观看 历史网站wordpress 用户
  • 灰色网站欣赏html5网站开发价格
  • 深圳网站建设总部免费企业名录搜索软件
  • 南京网站设计我选柚米科技ppt模板免费下载古风
  • 网站建设编程时注意事项代码html
  • 做文案公众号策划兼职网站京东网上商城和京东有什么区别
  • wordpress网站秒开wordpress资源分享网
  • 佛山顺德容桂网站制作网站建设与管理案例教程在线阅读
  • 网站项目计划书两学一做 网站
  • 陕西交通建设有限公司网站博客网站快速排名
  • 南昌网站建设700起网页模板之家
  • 建一个网站需要什么手续快速搭建网站后天台
  • 建站开发劳务 东莞网站建设
  • 东昌府聊城网站优化金山区网站制作
  • 政务网站建设外包网站问些什么问题
  • 网站开发学什么语言wordpress安装出错
  • 网站首页分类怎么做的wordpress安装主题连接不上ftp
  • 西安有啥好玩的地方郑州网站优化汉狮网络
  • 阿里云虚拟主机可以做两个网站吗asp.net网站开发全过程
  • 江西安福县建设局网站品牌网站建设相关问题