[英]Qt::make_shared for creating QSharedPtr as std::make_shared for creating std::shared_ptr
As stated in Bjarne Stroustrup's "A tour of C++", and as a known C++14 practice, one should avoid naked new
and delete
in the code. 正如Bjarne Stroustrup的“C ++之旅”中所述,并且作为已知的C ++ 14实践,应该避免在代码中使用裸
new
和delete
。 Standard library offers std::make_shared
and std::make_unique
for creating smart pointers to immediately store allocated objects in. 标准库提供了
std::make_shared
和std::make_unique
用于创建智能指针以立即存储已分配的对象。
However, it is not possible to use these routines for non-standard smart pointers, like in Qt. 但是,不可能将这些例程用于非标准智能指针,例如Qt。 Qt has its own memory management model (with parents), but also provides smart pointer classes like
QSharedPointer
and QPointer
(though the latter is not actually an owning pointer). Qt有自己的内存管理模型(带父
QSharedPointer
),但也提供了QSharedPointer
和QPointer
等智能指针类(尽管后者实际上并不是拥有指针)。
My question is: isn't it convenient to create Qt analogs of std::make_shared
? 我的问题是:创建
std::make_shared
Qt类似物不方便吗? Like this, for creating QSharedPtr
: 像这样,创建
QSharedPtr
:
namespace Qt
{
template<class T, class... Args>
QSharedPointer<T> make_shared(Args&&... args)
{
return QSharedPointer<T>(new T(std::forward<Args>(args)...));
}
}
Or like this, for creating QPointer
: 或者像这样,创建
QPointer
:
namespace Qt
{
template<class T, class... Args>
QPointer<T> make_ptr(Args&&... args)
{
return QPointer<T>(new T(std::forward<Args>(args)...));
}
}
And it can be used like: 它可以像:
auto pCancelButton = Qt::make_ptr<QPushButton>("Cancel", this);
Are there any caveats for this approach? 这种方法有什么警告吗? Are there any publicly known usage of this approach?
有这种方法的公开使用吗?
UPDATE I claim that Qt::make_ptr
is useful as long as QPointer
is useful, because it will hide new
operator and make sure new
is called only for something that inherits QObject
. 更新我声称只要
QPointer
很有用, Qt::make_ptr
QPointer
有用,因为它会隐藏new
运算符并确保只为继承QObject
东西调用new
。 Qt users do a lot of new
's, but in this way we can be sure new
is used only in Qt context. Qt用户做了很多
new
的,但是通过这种方式我们可以确定new
只在Qt上下文中使用。 Any arguments on this thought? 关于这个想法的任何争论?
Features such as make_shared
strictly rely on the perfect forwarding feature, which is only available since C++11 and the introduction of universal (forwarding) references . 诸如
make_shared
严格依赖于完美的转发功能,该功能仅在C ++ 11和引入通用(转发)引用时可用。 Having said that, without a perfect forwarding , using this function may be inefficient. 话虽如此,如果没有完美的转发 ,使用此功能可能效率低下。 Qt is quite older than the recent C++ standard, hence it was not available till Qt 5.1 (just like previously you had to use Qt's internal pre-processing macros like
SIGNAL
and SLOT
for making connections). Qt比最近的C ++标准要老,因此直到Qt 5.1才能使用它(就像之前你必须使用Qt的内部预处理宏,如
SIGNAL
和SLOT
进行连接)。
Qt 5.1 already provides its own implementation for making smart pointers for QSharedPointer . Qt 5.1已经提供了自己的实现,用于为QSharedPointer制作智能指针。
That static create
member function can be used as follows: 静态
create
成员函数可以使用如下:
auto ptr = QSharedPointer<QPushButton>::create("Cancel", this);
But note the description: 但请注意说明:
Note: This function is only available with a C++11 compiler that supports perfect forwarding of an arbitrary number of arguments.
注意:此函数仅适用于支持完全转发任意数量参数的C ++ 11编译器。 If the compiler does not support the necessary C++11 features, you must use the overload that calls the default constructor.
如果编译器不支持必要的C ++ 11功能,则必须使用调用默认构造函数的重载。
There are two major advantages of using make_shared
and create
functions rather than directly calling constructor with allocating memory with new
: 使用
make_shared
和create
函数有两个主要优点,而不是直接使用new
分配内存来调用构造函数:
That special perfectly forwarding function can allocate in a single system call a memory for both stored object and reference counter . 这种特殊的完美转发功能可以在单个系统中分配存储对象和引用计数器的内存。
The memory allocation is separated from the calling context, so you avoid memory leaks in case of an exception is thrown while constructing another object in eg a function call (where a compiler is free to choose the order in which arguments are evaluated). 内存分配与调用上下文分离,因此如果在例如函数调用中构造另一个对象时抛出异常,则可以避免内存泄漏(编译器可以自由选择评估参数的顺序)。 Consider:
考虑:
foo(QSharedPointer<QPushButton>(new QPushButton("Cancel", this)), MayThrow());
That is, if the compiler first executes the new QPushButton("Cancel", this)
expression, and then calls the MayThrow()
function before calling the constructor of QSharedPointer
, you may leak memory if the MayThrow()
function throws an exception. 也就是说,如果编译器将首先执行
new QPushButton("Cancel", this)
的表达,然后调用MayThrow()
调用的构造函数之前功能QSharedPointer
,你可以,如果泄漏内存MayThrow()
函数抛出异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.