这里引用了cppreference的实现说明部分std::shared_ptr,其中提到有两个不同的指针(如粗体所示):可以返回的指针get(),以及控制块中保存实际数据的指针.
在典型的实现中,
std::shared_ptr只保留两个指针:
- 存储的指针(返回一个
get())- 指向控制块的指针
控制块是一个动态分配的对象,它包含:
- 指向托管对象的指针或托管对象本身
- 删除(类型擦除)
- 分配器(类型擦除)
- 数量
shared_ptrs是自己的管理对象- 的数目
weak_ptrs引用该管理对象
shared_ptr直接保持的指针是由返回get()的指针,而控制块保持的指针或对象是当共享所有者的数量达到零时将被删除的指针或对象.这些指针不一定相等.
我的问题是,为什么托管对象需要两个不同的指针(两个粗体)(除了指向控制块的指针)?那个回来的人get()不够吗?为什么这些指针不一定相等?
这是来自Stroustrup的"C++编程语言"的代码,该代码实现了一个finally我无法理解析构函数被调用的地方.
template<typename F> struct Final_action
{
Final_action(F f): clean{f} {}
~Final_action() { clean(); }
F clean;
}
template<class F>
Final_action<F> finally(F f)
{
return Final_action<F>(f);
}
void test(){
int* p=new int{7};
auto act1 = finally( [&]{delete p;cout<<"Goodbye,cruel world\n";} );
}
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
根据作者的说法,delete p只有一次被调用:当act1超出范围时.但是从我的理解:首先,act1将使用复制构造函数初始化,然后Final_action<F>(f)函数中的临时对象finally被破坏,delete p第一次调用,然后在函数结束test时第二次act1超出范围.我哪里弄错了?
为什么finally需要这个功能?我不能只定义Final_action act1([&]{delete p;cout<<"Goodbye,cruel world\n"})?那是一样的吗?
此外,如果有人能想到更好的标题,请修改当前的标题.
更新:在进一步思考之后,我现在确信析构函数可能会被调用三次.另外一个是用于在调用函数中自动生成的临时对象,void test()用作复制构造函数的参数act1.这可以通过-fno-elide-constructorsg ++中的选项进行验证.对于那些和我有同样问题的人,请参阅Bill Lynch在答案中指出的复制省略 …