我正在使用Qt5和QMAKE_CXXFLAGS += -std=c++1y
启动一个新项目。我不确定我应该选择QScopedPointer
还是std::unique_ptr
。
我读了somewhere,发现QScopedPointer
不再那么酷了。QScopedPointer
是否具有unique_ptr
缺少的任何功能?替换unique_ptr
时,我是否不想使用QScopedPointer
的任何功能?或相反亦然?
最佳答案
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删除器映射到标准删除器。另一种方法是由删除器无状态限制的:
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, class D>
QScopedPointer<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
,反之亦然。数组delete
QScopedPointer
应该转换为unique_ptr<T[]>
,反之亦然。在其他情况下,我只是包装删除器。从理论上讲,一个真正的花哨的技巧是注意到传入的删除程序是否已经包装好并反转了包装,但是如果您的代码进行了那么多次往返,则可能已经出现了问题。
关于c++ - 我应该使用QScopedPointer还是std::unique_ptr?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40346393/