提问人:Arun 提问时间:4/8/2014 最后编辑:phsArun 更新时间:4/8/2014 访问量:3489
C++ 零法则:多态性删除和unique_ptr行为
C++ Rule of Zero : polymorphic deletion and unique_ptr behavior
问:
在最近的重载日志中,主题为“强制执行零规则”,作者描述了我们如何避免编写五运算符规则,因为编写它们的原因如下:
- 资源管理
- 多态性缺失
这两者都可以通过使用智能指针来解决。
在这里,我对第二部分特别感兴趣。
请考虑以下代码片段:
class Base
{
public:
virtual void Fun() = 0;
};
class Derived : public Base
{
public:
~Derived()
{
cout << "Derived::~Derived\n";
}
void Fun()
{
cout << "Derived::Fun\n";
}
};
int main()
{
shared_ptr<Base> pB = make_shared<Derived>();
pB->Fun();
}
在这种情况下,正如本文的作者所解释的那样,我们通过使用共享指针来获得多态删除,这确实有效。
但是如果我用 替换 ,我就不能再观察到多态性删除了。shared_ptr
unique_ptr
现在我的问题是,为什么这两种行为不同?为什么处理多态性缺失而不处理?shared_ptr
unique_ptr
答:
template<typename T>
using smart_unique_ptr=std::unique_ptr<T,void(*)(void*)>;
template<class T, class...Args> smart_unique_ptr<T> make_smart_unique(Args&&...args) {
return {new T(std::forward<Args>(args)...), [](void*t){delete (T*)t;}};
}
问题在于对存储指针的调用的默认删除程序。上面存储了一个在构造时知道类型的删除器,因此当复制到基类时仍将作为子类删除。unique_ptr
delete
unique_ptr
这增加了适度的开销,因为我们必须取消引用指针。此外,它还使类型非规范化,因为默认构造的 s 现在是非法的。你可以通过一些额外的工作来解决这个问题(用一个至少不会崩溃的半智能函子替换一个原始函数指针:但是,如果调用删除器时 是非空的,则应断言函数指针存在)。smart_unique_ptr
unique
评论
default_delete
如果您使用 C++14 或像 Yakk 的答案那样编写自己的 14,它会起作用。基本上,共享指针行为之间的区别在于,您可以获得:make_unique
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
正如你所看到的,删除器属于该类型。如果声明 a,它将始终用作默认值。但会注意为您的类使用正确的删除器。unique_pointer
unique_pointer<Base>
std::default_delete<Base>
make_unique
使用时,您可以获得:shared_ptr
template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );
和其他重载作为构造函数。正如你所看到的,默认的删除器在声明类型时取决于模板参数(除非你使用 ),而对于删除器取决于传递给构造函数的类型。unique_ptr
make_unique
shared_ptr
您可以在此处看到一个允许使用虚拟析构函数进行多态删除的版本(此版本也应该在 VS2012 中工作)。请注意,它被黑客入侵了,我目前不确定 和 在 C++14 中的行为会是什么样子,但我希望他们能使这更容易。也许我会查看C++14添加的论文,看看如果我以后有时间,是否会有什么变化。unique_ptr
make_shared
评论
答案在这里:https://stackoverflow.com/a/22861890/2007142
报价:
一旦最后一个引用超出范围或被重置,将被调用并释放内存。因此,您不需要进行虚拟化。 并且不要提供此功能,因为它们不提供与删除器相关的机制,因为唯一指针要简单得多,并且旨在降低开销,因此不存储删除器所需的额外函数指针。
shared_ptr
~Derived()
~Base()
unique_ptr<Base>
make_unique<Derived>
shared_ptr
评论
unique_pointer
std::shared_ptr
std::shared_ptr
std::unique_ptr