我正在启动一个新项目,使用Qt5和QMAKE_CXXFLAGS += -std=c++1y
。我不确定是否应该使用QScopedPointer
还是std::unique_ptr
。
我在某个地方读到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);
}
};
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
,反之亦然。
数组删除器 QScopedPointer
应该转换为 unique_ptr<T[]>
,反之亦然。
在其他情况下,我只是简单地包装删除器。理论上,一个非常高级的技巧是注意到传入的删除器是否已经被包装,然后反向包装,但如果您的代码需要做那么多往返操作,那么可能已经出现了某些问题。
QScopedPointer
真正适用于 C++98 代码库(这也是 QScopedPointer
没有移动语义的原因)。考虑到你甚至无法移动它,它通常只是一种实现帮助工具,并且你不会在任何 API 中看到它的使用(不像 unique_ptr
)。Qt 项目有意不使 QScopedPointer
变得更好 - 你已经有了那个,就是 unique_ptr
。在新的、启用了 C++11 的项目中,请使用 unique_ptr
而不是 QScopedPointer
。 - peppeto_qt
和to_std
。 - Yakk - Adam Nevraumont为什么会使用非标准库的东西而不是标准库中的东西呢?
对我来说,只有一个好程序员会这样做的原因:如果外部库提供了标准库没有提供的功能。这是这种情况吗?
考虑您的程序的可移植性和未来的更新,然后做出决定。
尽管这两个类的主要意图相似,但它们之间有一个重要的区别,这使您需要做出某些业务决策。
QScopedPointer没有赋值运算符。而std::unique_ptr有赋值运算符。
如果您想在QT对象/控件上严格执行并且不想使用赋值,请使用QScopedPointer。
const unique_ptr
同样没有赋值运算符。 - Howard Hinnant
std::unique_ptr
。 - NathanOliverstd::shared_ptr
和std::unique_ptr
。 - drescherjm