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

new一个指针再被智能指针接管和直接调用make_unique有什么区别? (接上篇的未完待续)

上篇代码有错误在本篇幅更正#include iostream #include memory #include vector #include utility #include cstddef #include type_traits //std::enable_if_t!std::is_arrayT::value, int 0 template typename T struct DefaultDelete { //必须加const为了兼容后面const类型的智能指针 void operator()(T* ptr) const { if (ptr) { std::cout use T deleter_() std::endl; delete ptr; } } }; //利用模板的特化去匹配数组类型 template typename T struct DefaultDeleteT[] { void operator()(T *ptr) const { if (ptr) { std::cout use T[] deleter_() std::endl; delete[] ptr; } } }; template typename T, typename Delete DefaultDeleteT class MyUniquePtr { private: T *ptr_; Delete deleter_; public: //允许外部自定义删除类在构造函数这里传入, 所以也需要移动构造删除器 inline explicit MyUniquePtr(T *data, Delete del Delete()) : ptr_(data), deleter_(std::move(del)) { std::cout MyUniquePtrT std::endl; } inline ~MyUniquePtr() noexcept { if (ptr_) { std::cout ~MyUniquePtrT std::endl; deleter_(ptr_); ptr_ nullptr; } } MyUniquePtr(const MyUniquePtr ptr) delete; MyUniquePtr operator(const MyUniquePtr ptr) delete; inline MyUniquePtr(MyUniquePtr other) : ptr_(other.ptr_), deleter_(std::move(other.deleter_)) { other.ptr_ nullptr; } inline MyUniquePtr operator (MyUniquePtr other) { if (this other) { return *this; } reset(other.ptr_); deleter_ std::move(other.deleter_); other.ptr_ nullptr; return *this; } inline T operator* () const noexcept { return *ptr_; } inline T* operator- () const noexcept { return ptr_; } inline explicit operator bool() const noexcept { return (ptr_ ! nullptr); } inline void reset(T *data) { T *tmp ptr_; ptr_ data; if (tmp) { deleter_(tmp); } } T *get_ptr() const noexcept { return ptr_; } }; template typename T, typename Delete class MyUniquePtrT[], Delete { private: T *ptr_; Delete deleter_; public: inline explicit MyUniquePtr(T *data, Delete del Delete()) : ptr_(data), deleter_(std::move(del)) { std::cout MyUniquePtrT[] std::endl; } inline ~MyUniquePtr() noexcept { if (ptr_) { std::cout ~MyUniquePtrT[] std::endl; deleter_(ptr_); ptr_ nullptr; } } MyUniquePtr(const MyUniquePtr ptr) delete; MyUniquePtr operator(const MyUniquePtr ptr) delete; inline MyUniquePtr(MyUniquePtr other) : ptr_(other.ptr_), deleter_(std::move(other.deleter_)) { other.ptr_ nullptr; } inline MyUniquePtr operator (MyUniquePtr other) { if (this other) { return *this; } reset(other.ptr_); deleter_ std::move(other.deleter_); other.ptr_ nullptr; return *this; } inline explicit operator bool() const noexcept { return (ptr_ ! nullptr); } inline void reset(T *data) { T *tmp ptr_; ptr_ data; if (tmp) { deleter_(tmp); } } /* 不用int原因是禁止负索引 */ inline T operator[] (size_t index) const { return ptr_[index]; } T *get_ptr() const noexcept { return ptr_; } }; templatetypename T, typename ... Args, std::enable_if_t!std::is_arrayT::value, int 0 MyUniquePtrT myMakeUnique(Args ... args) { return MyUniquePtrT(new T(std::forwardArgs(args)...)); } templatetypename T, std::enable_if_tstd::is_arrayT::value std::extentT::value 0, int 0 MyUniquePtrT myMakeUnique(size_t size) { return MyUniquePtrT(new std::remove_extent_tT[size]()); } int main() { MyUniquePtrint[] p myMakeUniqueint[](6); MyUniquePtrint a myMakeUniqueint(); }构造函数里面 Delete del Delete() 为什么这样写可以这样写吗 Delete del deleter_因为template typename T, typename Delete DefaultDeleteT 这里typename Delete默认就是DefaultDeleteT 这个类所以说Delete()编译器能找到与之匹配的实体类DefaultDeleteDelete()相当于DefaultDeleteT(), 直接写DefaultDeleteT()也行只不过声明模板时候已经写了默认等于DefaultDeleteT 为了简写直接Delete()就好。Delete del deleter_正确吗本意是用类内默认构造器对象但是问题在于这是在构造函数内部类中变量都没有分配内存完成就直接用整个MyUniquePtr类没有构建出来时候, 也就是没有定义实体对象时候, 也就是MyUniquePtr p; 没有定义对象没有实体内存分配出来时, deleter_没有内存里面的成员变量直接用会导致未定义行为调用Delete类中拷贝构造时候, 用到deleter_入参传入但是deleter连内存都没有, 直接出现了问题所以最好用Delete() 现用现构造技巧(单例模式) 出临时对象, 去拷贝构造给deleterC中make_unique调用函数有啥好处注意C17之前函数参数里面的执行顺序是不确定的, 可能存在交替执行的流程之前的new操作是暴露在外的用effective c中的例子函数声明 int priority(); void processWidget(std::shared_ptrWidget pw, int priority_); 函数调用 processWidget(std::shared_ptrWidget(new Widget), priority()); C17之前参数里的执行顺序是不确定的, 上述代码会有什么问题 执行顺序 1. new Widget堆中构造内存 2. std::shared_ptrWidget智能指针接管 3. priority() 如果真的按照上述流程执行那就没问题, 也即C17现在是没问题的, C17能保证先完成一个参数处理完事再处理下一个参数 但是C17之前 可能会这样执行顺序 1. new Widget堆中构造内存 2. priority() 3. std::shared_ptrWidget智能指针接管 如果priority()函数抛异常 那么堆内存没有被智能指针接管导致内存泄漏这就是问题make_unique优势在哪里能解决上面讨论的这个问题?make_unique利用工厂模式, 用到时候去构造临时对象返回一个对象他把分配堆内存和智能指针接管操作凑在一个函数体执行这样能把他俩操作绑定成一个函数操作processWidget(std::make_uniqueWidget(), priority()); 这样流程会不会有问题执行顺序1. std::make_uniqueWidget()代码执行由于将分配内存和智能指针接管变成一个操作那么不是他先就是priority()先假如1. std::make_uniqueWidget()2. priority()此时priority()抛出异常那么堆内存已经被智能指针接管了不会泄漏然后由于泡异常C能保证函数执行过程中抛异常函数展开栈内存会得到释放所以智能指针对象被析构即堆内存被释放掉所以强异常安全。换个执行顺序同理总之能用make_unique构造智能指针就用他吧
http://www.zskr.cn/news/1360170.html

相关文章:

  • 中国AI调用量是美国的2倍,但真正重要的不是这个数字
  • AI Agent写作如何重构内容生产力:3个已被验证的行业增效模型及ROI测算公式
  • GalTransl:面向视觉小说的AI驱动翻译系统架构解析
  • 从频繁处理超时到稳定响应谈谈我使用Taotoken路由能力后的改变
  • 西恩士液冷板清洁度全自动显微镜分析:AI驱动的高通量检测革命 - 工业设备研究社
  • 高端设计制造业SD-WAN跨域组网深度解析:头部无人机企业如何实现异地数据高效安全回传和协作
  • 跨境电商标题焦虑?QA揭秘“批量更新标题“如何拯救你的运营效率
  • 体验 Taotoken 官方价折扣与活动价带来的实际成本优势
  • 五轴龙门机床厂家推荐,五轴龙门机床哪家好?
  • 合规对标·低误报漏报·稳定运行——知源-AI数据分类分级系统金融行业解决方案
  • 如何用ElegantBook快速创建专业学术书籍:LaTeX排版终极指南
  • 5个关键问题解答:如何高效部署和使用Open WebUI本地AI平台
  • 国内高校毕业生必备的AI论文写作软件是哪款?
  • AI Agent不是替代ML工程师,而是放大17倍生产力——基于200+生产案例的效能归因分析
  • WSA-Pacman终极指南:三步搞定Windows安卓应用,告别命令行烦恼
  • 关于fiddler报错“The system proxy was changed. click to reenable capturing”的解决办法
  • 22. 与 React 集成
  • 20. JSX 支持
  • 微电网协调控制柜 vs 传统配电柜:本质差异与代际跨越
  • 用 MapleSim 卷绕和卷材加工仿真库加速智能制造与电池产线优化
  • ngx_http_find_virtual_server
  • 清除缓存,释放C盘
  • Taotoken 的 API Key 权限管理与审计日志功能在安全开发中的价值
  • 游戏NPC不再脚本化!Unity+LangChain Agent实时剧情生成技术,上线72小时用户时长↑43%
  • 自定义中间件限流limit
  • 酒店客控系统十大品牌2026排行-技术路线与选型建议
  • 分享一个Python爬虫的小技巧
  • 面部美化 API 集成指南
  • 蒲公英R300重磅升级!串口数据采集与MQTT上云一步到位!
  • RadexMarkets瑞德克斯:到账时效与影响因素的客观说明