当您使用unique_ptr<T>
作为转发声明类型T
时,unique_ptr
析构函数要求T
完成,但移动赋值运算符也是如此(和{ {1}}),根据此表:
https://stackoverflow.com/a/6089065/1794803
因此,对于您的reset
惯用语,要正确实现它,您必须声明pImpl
和delete
(作为副作用,将其标记为非内联):
move assignment method
但是,由于class impl_t;
class A
{
std::unique_ptr<impl_t> p_impl;
public:
// Implement in A.cpp as A::~A() = default;
~A();
// Implemented in A.cpp as A& operator=(A&&) = default;
A& operator=(A&& he);
};
是动态内存的RAII解决方案,并且std::unique_ptr
已经在一个类中,并且您无论如何都被迫编写析构函数,不是更好只管理一个原始指针,因为从pImpl
的角度来看,你的类已经是类RAII了?:
p_impl
难道这不是一个更好的解决方案吗? (+如果你想上课,可以定义或删除你自己的复制/移动操作员是可复制的/可移动的;但这是一个有意识的选择&#34 ;;但是,不要为{编写移动任务{1}}是一个错误。)
使用class impl_t;
class A
{
impl_t* p_impl;
public:
~A(); // The destructor must be written anyway.
// The omitted move assignment destructor doesn't cause UB.
};
只能保存您在析构函数中编写的unique_ptr
,无论如何都必须声明。
unique_ptr
是本地动态对象的最佳选择,即使在例外的情况下也会被破坏,但对于&#34;属性&#34;,如果你没有&#34,你只能获得UB的可能性39;记住你必须重写移动赋值操作符。
答案 0 :(得分:4)
好吧,使用std::unique_ptr
赎回了您为 delete
明确p_impl
而烦恼。
此外,它应该在构造函数中的并发访问和异常情况下运行良好(似乎不能保证使用原始指针和new
自己)。
答案 1 :(得分:0)
std :: unique_ptr应该是pimpl的首选方式。作为参考,请在大约10分钟后查看Herb Sutter's talk at CppCon16。 原因是,它可以防止你在使用RAII时意外更改你的pimpl。