C ++ / pimpl:原始指针还是unique_ptr?什么是更好的选择?

时间:2016-12-10 17:34:38

标签: c++ unique-ptr raii raw-pointer

当您使用unique_ptr<T>作为转发声明类型T时,unique_ptr析构函数要求T完成,但移动赋值运算符也是如此(和{ {1}}),根据此表:

https://stackoverflow.com/a/6089065/1794803

因此,对于您的reset惯用语,要正确实现它,您必须声明pImpldelete(作为副作用,将其标记为非内联):

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;记住你必须重写移动赋值操作符。

2 个答案:

答案 0 :(得分:4)

好吧,使用std::unique_ptr赎回了您为 delete 明确p_impl而烦恼。

此外,它应该在构造函数中的并发访问和异常情况下运行良好(似乎不能保证使用原始指针和new自己)。

答案 1 :(得分:0)

std :: unique_ptr应该是pimpl的首选方式。作为参考,请在大约10分钟后查看Herb Sutter's talk at CppCon16。 原因是,它可以防止你在使用RAII时意外更改你的pimpl。