@H_502_1@我正在开始一个新项目,使用Qt5和QMAKE_CXXFLAGS = -std = c 1y.我不确定我是否应该选择QScopedPointer或std :: unique_ptr.
我读了somewhere,QScopedPointer不再那么酷了.
QScopedPointer是否具有unique_ptr缺少的任何功能?替换QScopedPointer时是否有任何我不想要的unique_ptr功能?或相反亦然?
解决方法
QScopedPointer严格弱于unique_ptr,因为它不支持移动语义.
它的功能非常相似.
移动语义非常有用,并且意外地错误地使用它们来引起问题是极其罕见的.所以他们从无害到(更典型)有用.
关于使用QScopedPointer的唯一原因是与现有代码库的互操作性;甚至在那里,鉴于它们有多么相似,适配器将非常简单.
因此,如果您不需要调整,请使用unique_ptr.
我现在讨论适应.
棘手的部分是QScopedPointer的第二个参数.它非常粗略地对应于unique_ptr的第二个参数.
在unique_ptr中,允许有状态删除.在QScopedPointer中,它们不是.该
static void cleanup(T* pointer)
对应于
void operator()(T* pointer)const
在unique_ptr中以一对一的方式进行.所以:
template<class QDelete> struct std_deleter { template<class T> void operator()(T* target) const { QDelete::cleanup(target); } };
将Qt删除器映射到std删除器.另一种方式受限于删除者是无国籍的:
template<class Std_deleter> struct Qt_deleter { template<class T> static void cleanup(T* target) { static_assert(std::is_empty<Std_deleter>{},"Only works with stateless deleters"); Std_deleter{}(target); } };
我们现在可以转换:
template<class T,class D> QScopedPointer<T,Qt_deleter<D>> to_qt( std::unique_ptr<T,D>&& src ) { return src.release(); } template<class T,Qt_deleter<D>> to_qt( std::unique_ptr<T[],D>&& src ) { return src.release(); } template<class T> QScopedPointer<T> to_qt( std::unique_ptr<T>&& src ) { return src.release(); } template<class T> QScopedPointer<T,QScopedPointerArrayDeleter> to_qt( std::unique_ptr<T[]>&& src ) { return src.release(); } template< class T,class D,class R=std::unique_ptr<T,std_deleter<D> > > to_std( QScopedPointer<T,D>&& src ) { return R(src.take()); // must be explicit } template<class T,class R=std::unique_ptr<T>> to_std( QScopedPointer<T>&& src ) { return R(src.take()); // must be explicit } template<class T,class R=std::unique_ptr<T[]>> to_std( QScopedPointer<T,QScopedPointerArrayDeleter >&& src ) { return R(src.take()); // must be explicit }
这涵盖了您使用QScopedPointer的唯一原因.有一些极端情况 – 默认删除器QScopedPointer应该转换为默认的std :: unique_ptr,反之亦然.
应将数组删除QScopedPointer转换为unique_ptr< T []>反之亦然.
在其他情况下,我只是包装删除器.理论上,一个非常奇特的技巧是注意到传入的删除器是否已经被包裹并反转包装,但如果你的代码执行了那么多次往返,那么可能已经出现了问题.