void del(void(*)()) {}
void fun() {}
int main()
{
std::shared_ptr<void()> ee(fun, del);
(*ee)();
}
Run Code Online (Sandbox Code Playgroud)
这是在cppreference.com上找到的一段代码,我试图理解 shared_ptr 的用途,这是我遇到的一个例子。我尝试运行它并对其进行一些修改,例如在函数体内添加 cout 语句,但我无法理解这里到底发生了什么。
添加更多与我的疑问相关的背景信息,
我的疑惑具体包括:
std::shared_ptr<void()>ee(fun);?Run Code Online (Sandbox Code Playgroud)template <class Y, class Deleter> std::shared_ptr(Y* ptr, Deleter d);
shared_ptree 是用一个函数初始化的,那么为什么它根本std::shared_ptr<void()>ee(fun);不起作用呢?要点是创建一个上下文,del无论声明fun的函数中发生了什么,都会在该上下文中调用ee。它可以防止提前退货和例外情况。
ee(我假设shared_ptr实现是一个类)?fun是否可以使共享指针认为它拥有资源,以便在超出范围时调用Deleter函数。ee
del必须接受函数指针作为参数?这有什么意义呢?这是因为它将使用指向它所拥有的资源的指针来shared_ptr调用Deleter函数。因为它是一个函数指针,所以它实际上不能delete- 但需要它来履行您在创建指向函数的共享指针时制定的合同。
取消引用ee并调用结果是为了清楚起见。它本来也可以fun();,但(*ee)();应该让代码的读者看到调用和函数返回时fun调用的必要性之间的紧密联系。del它不是一个“真正的”上下文处理程序,因为它会出现错误:
template <class Y, class Deleter>
std::shared_ptr(Y* ptr, Deleter d);
Run Code Online (Sandbox Code Playgroud)
不使用 using 的类似构造shared_ptr可能如下所示:
{
std::shared_ptr<void()> ee(fun, del);
// here someone mistakenly adds an early return:
if (argc == 123) return 1;
(*ee)(); // or fun();
} // del may now be called even if `fun` was never called
Run Code Online (Sandbox Code Playgroud)
另一个例子:
void del() {}
void fun() {}
template <class Out>
struct call_context {
template <class In, class O, class... Args>
call_context(In&& in, O&& o) : f(std::forward<O>(o)) {
std::invoke(std::forward<In>(in));
}
~call_context() { f(); }
Out f;
};
template <class In, class Out>
call_context(In&&, Out&&) -> call_context<Out>;
int main()
{
// call fun and will call del later no matter how `main` is exited:
call_context cc(fun, del);
}
Run Code Online (Sandbox Code Playgroud)
输出:
#include <iostream>
// same call_context definition as above
void fun() {
std::cout << "Fun called\n";
}
int main() {
call_context cc(fun, [] { std::cout << "main exited\n"; });
std::cout << "---\n";
}
Run Code Online (Sandbox Code Playgroud)