源代码为:
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最合适。