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

spdlog源码学习:std::unique_ptr订制删除器,guard用法,以及decltype

源代码为:

C:\work\hchx\HchxKernel\PublicAPI\spdlog\fmt\bundled\args.htemplate <typename T>void emplace_arg(const detail::named_arg<char_type, T>& arg) {if (named_info_.empty()) {constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};data_.insert(data_.begin(), {zero_ptr, 0});}data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {data->pop_back();};std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>guard{&data_, pop_one};named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});data_[0].value_.named_args = {named_info_.data(), named_info_.size()};guard.release();}

取出其中的一部分,观察guard的概念:

1、std::unique_ptr肯定会析构,除非提前release出来,交出管理权

//unique_ptr的自定义删除器
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {data->pop_back();
};std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>guard{&data_, pop_one};named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});data_[0].value_.named_args = {named_info_.data(), named_info_.size()};//如果上面两行代码又异常提前退出。代码就会跳到pop_one里,进行回退,也就是pop_back
guard.release();

下面研究下unique_ptr自定义删除器的用法

note:这种写法,在C++14下编译不过:lambda 不能出现在未计算的上下文中
必须更高的版本。
自定义的实现不能写在std::unique_ptr的尖括号的里面auto main()->int{// 未求值的lambda,g++ main.cpp -std=c++20// 适合单次使用,不适合做接口,因为lambda表达式在每次使用都属于不同的类型std::unique_ptr<FILE, decltype([](FILE* fp){fclose(fp); fp = nullptr; 
std::cout << "file auto closed.\n";})> 
pfile(fopen("3.txt", "w"));
}
}
————————————————版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。原文链接:https://blog.csdn.net/liugan528/article/details/139031545

得写成这样

注意,初始化pfile时的第二个参数。要把del传给它。auto fun3()->int {auto del = [](FILE* fp)->void {fclose(fp);fp = nullptr; std::cout << "file auto closed.\n"; };// 未求值的lambda,g++ main.cpp -std=c++20// 适合单次使用,不适合做接口,因为lambda表达式在每次使用都属于不同的类型std::unique_ptr < FILE, decltype(del) >pfile(fopen("3.txt", "w"), del);return 1;
}

再来一个

void fun4()
{auto del = [](FILE* fp)->void {fclose(fp);fp = nullptr; std::cout << "file auto closed.\n"; };auto delLambda = [](int* p) { delete p; };std::unique_ptr<int, decltype(delLambda)> p3(nullptr, delLambda);
}

注意上面例子中decltype的用法,auto的类型用decltype进行推导。

看看别人的例子,展示了std::function用于删除器时,字节消耗的最多

https://developer.aliyun.com/article/983223void Delete(int* p) { delete p; }
auto delLambda = [](int* p) { delete p; };
std::function<void (int*)> delFunc = delLambda;int main()
{std::unique_ptr<int>                      p1(nullptr);std::unique_ptr<int, decltype(Delete)*>   p2(nullptr, Delete);std::unique_ptr<int, decltype(delLambda)> p3(nullptr, delLambda);std::unique_ptr<int, decltype(delFunc)>   p4(nullptr, delFunc);std::cout << "Default  deleter: " << sizeof(p1) << std::endl;std::cout << "FuncPtr  deleter: " << sizeof(p2) << std::endl;std::cout << "Lambda   deleter: " << sizeof(p3) << std::endl;std::cout << "Function deleter: " << sizeof(p4) << std::endl;return 0;
}// Default  deleter: 8
// FuncPtr  deleter: 16
// Lambda   deleter: 8
// Function deleter: 40可以看到:
使用函数指针作为删除器产生的std::unique_ptr 对象大小为 16 字节,
使用 std::function 则为 40 字节,
而使用无状态 lambda 和默认删除器均为 8 字节,
果真没有引入额外的内存开销。看来还是lambda最合适。

相关文章:

  • Python面试整理-Python中的函数定义和调用
  • Linux工具相关介绍
  • 网络通讯实验报告
  • jenkins 使用教程
  • 3226 使两个整数相等的位更改次数
  • 鸿蒙OpenHarmony Native API【HiLog】
  • PyQt5学习路线
  • 上海昇腾AI训练营笔记
  • mysql8和mysql5版本在使用mybatis框架时的注意事项
  • 主流大数据调度工具DolphinScheduler之数据采集
  • 移动硬盘在苹果电脑上使用后在windows中无法读取 Win和Mac的硬盘怎么通用
  • 如何通过成熟的外发平台,实现文档安全外发管理?
  • 快速认识EA(Enterprise Architecture)
  • JVM--HostSpot算法细节实现
  • 华为eNSP模拟器安装
  • 【译】理解JavaScript:new 关键字
  • Brief introduction of how to 'Call, Apply and Bind'
  • ECS应用管理最佳实践
  • Java 最常见的 200+ 面试题:面试必备
  • Laravel 实践之路: 数据库迁移与数据填充
  • QQ浏览器x5内核的兼容性问题
  • Xmanager 远程桌面 CentOS 7
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 分类模型——Logistics Regression
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 前端攻城师
  • 思否第一天
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 推荐一个React的管理后台框架
  • 协程
  • 最简单的无缝轮播
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • ### RabbitMQ五种工作模式:
  • $().each和$.each的区别
  • $nextTick的使用场景介绍
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (52)只出现一次的数字III
  • (第30天)二叉树阶段总结
  • (二)延时任务篇——通过redis的key监听,实现延迟任务实战
  • (二十四)Flask之flask-session组件
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (力扣)循环队列的实现与详解(C语言)
  • (七)Activiti-modeler中文支持
  • (十六)串口UART
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • .NET Core 成都线下面基会拉开序幕
  • .net 反编译_.net反编译的相关问题
  • .netcore 获取appsettings
  • .Net实现SCrypt Hash加密
  • .NET中的Exception处理(C#)