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

源代码为:

C:\work\hchx\HchxKernel\PublicAPI\spdlog\fmt\bundled\args.h

 template <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/983223


void 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最合适。

相关推荐

  1. spdlog学习

    2024-07-20 16:38:03       51 阅读
  2. spdlog解析

    2024-07-20 16:38:03       26 阅读
  3. spdlog 日志库部分说明

    2024-07-20 16:38:03       35 阅读
  4. 110 C++ decltype含义,decltype 主要用途

    2024-07-20 16:38:03       37 阅读
  5. C/C++中decltype关键字用法总结

    2024-07-20 16:38:03       159 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-20 16:38:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-20 16:38:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-20 16:38:03       45 阅读
  4. Python语言-面向对象

    2024-07-20 16:38:03       55 阅读

热门阅读

  1. 【Spring Boot 自定义配置项详解】

    2024-07-20 16:38:03       19 阅读
  2. 13、.Net相关的书籍 - .Net循序渐进系列文章

    2024-07-20 16:38:03       20 阅读
  3. OpenWrt安装快速入门指南

    2024-07-20 16:38:03       21 阅读
  4. K8S私有云 服务器负载均衡器OpenELB

    2024-07-20 16:38:03       20 阅读
  5. 基于深度学习的天气预报

    2024-07-20 16:38:03       20 阅读
  6. 设计模式-建造者模式

    2024-07-20 16:38:03       19 阅读
  7. 基于 Gunicorn、Flask 和 Docker 的 Web 应用开发

    2024-07-20 16:38:03       21 阅读