我正在使用Qt5和QMAKE_CXXFLAGS += -std=c++1y启动一个新项目。我不确定我应该选择QScopedPointer还是std::unique_ptr。
我读过somewhere,QScopedPointer不再那么酷了。
QScopedPointer是否有unique_ptr所缺乏的特性?在替换unique_ptr时,是否有我不想使用的QScopedPointer特性?反之亦然?
发布于 2016-10-31 17:06:31
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, 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[]>,反之亦然。
在其他情况下,我只是简单地结束删除。理论上,一个非常奇妙的技巧是注意到传入删除器是否已经被包装并反转包装,但是如果您的代码正在执行那么多的往返旅行,那么可能已经有问题了。
发布于 2016-10-31 16:56:22
为什么要使用标准库中的东西而不是标准库中的东西?
对我来说,任何优秀的程序员都会这么做,只有一个原因:如果外部库提供了标准库没有提供的东西。是这样吗?
考虑您的程序的可移植性和将来的更新,然后作出决定。
发布于 2016-10-31 16:39:34
尽管这两个类的主要意图是相似的,但这两个类之间的一个重要区别使您可以做出一些业务决策。
QScopedPointer没有赋值运算符。其中std::unique_ptr有赋值运算符.
如果您希望严格执行QT对象/控件,并且不希望进行赋值,请使用QScopedPointer。
https://stackoverflow.com/questions/40346393
复制相似问题