问题描述
我正在使用Qt5和 QMAKE_CXXFLAGS + = -std = c ++ 1y
开始一个新项目。我不确定是否应该使用 QScopedPointer
还是 std :: unique_ptr
。
I'm starting a new project, using Qt5 and QMAKE_CXXFLAGS += -std=c++1y
. I'm not sure whether I should prefer QScopedPointer
or std::unique_ptr
.
我读了 QScopedPointer
不再那么酷了。
I read somewhere that QScopedPointer
is not that cool any more.
QScopedPointer
是否具有 unique_ptr
缺少的功能?替换 QScopedPointer
时,我是否不想使用 unique_ptr
的任何功能?
Does QScopedPointer
have any features unique_ptr
lacks? Are there any features of unique_ptr
that I wouldn't want in when replacing QScopedPointer
? Or vice versa?
推荐答案
QScopedPointer
严格小于 unique_ptr
,因为它不支持移动语义。
QScopedPointer
is strictly weaker than unique_ptr
as it does not support move semantics.
其功能在其他方面极为相似。
Its functionality is otherwise extremely similar.
移动语义非常有用,而偶然不正确地使用它们引起问题的情况极为罕见。因此,它们的变化从无害到(通常)有用。
Move semantics are extremely useful, and accidentally using them incorrectly to cause problems is extremely rare. So they vary from harmless to (more typically) helpful.
关于您应该使用 QScopedPointer
的唯一原因是互操作性现有的代码库;
About the only reason you should use QScopedPointer
is interoperability with existing code bases; and even there, given how similar they are, an adapter would be pretty easy.
因此,如果它们是如此相似,那么适配器将非常容易。因此,如果不需要调整,请使用 unique_ptr
。
So if you don't need to adapt, use unique_ptr
.
我现在将讨论适应。
棘手的部分是 QScopedPointer
的第二个参数。它非常近似地对应于 unique_ptr
的第二个参数。
The tricky part is the 2nd parameter to QScopedPointer
. It very roughly corresponds to the 2nd parameter of unique_ptr
.
在 unique_ptr
有状态的删除器是允许的。在 QScopedPointer
中,它们不是。
In unique_ptr
stateful deleters are permitted. In QScopedPointer
they are not. The
static void cleanup(T* pointer)
对应于
void operator()(T* pointer)const
在 unique_ptr
中很漂亮一个基础。因此:
in the unique_ptr
in a pretty one-to-one basis. So:
template<class QDelete>
struct std_deleter {
template<class T>
void operator()(T* target) const {
QDelete::cleanup(target);
}
};
将Qt删除器映射到标准删除器。另一种方式是由删除器无状态限制的。
maps a Qt deleter to a std deleter. The other way is limited by the deleter being stateless:
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
,反之
which covers about the only reason why you'd use QScopedPointer
. There are a few corner cases -- the default deleter QScopedPointer
should be converted to a default std::unique_ptr
and vice versa.
删除数组 QScopedPointer
的对象应转换为 unique_ptr< T [] >
,反之亦然。
The array delete QScopedPointer
should be converted to a unique_ptr<T[]>
and vice versa.
在其他情况下,我只是包装了删除程序。从理论上讲,一个真正的花哨的技巧是注意到传入的删除程序是否已经包装好并反转了包装,但是如果您的代码进行了多次往返,则可能已经出了问题。
In other cases, I simply wrap up the deleter. In theory, a really fancy trick would be to notice if the incoming deleter was already wrapped up and reverse the wrapping, but if your code is doing that many round-trips there is probably already something wrong.
这篇关于我应该使用QScopedPointer还是std :: unique_ptr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!