Qt::make_shared 用于创建 QSharedPtr 作为 std::make_shared 用于创建 std::shared_ptr

问题描述 投票:0回答:1

正如 Bjarne Stroustrup 的“C++ 之旅”中所述,并且作为一种已知的 C++14 实践,应该避免在代码中使用裸露的

new
delete
。标准库提供
std::make_shared
std::make_unique
用于创建智能指针以立即存储分配的对象。

但是,无法将这些例程用于非标准智能指针,例如在 Qt 中。 Qt 有自己的内存管理模型(有父级),但也提供了智能指针类,如

QSharedPointer
QPointer
(尽管后者实际上并不是拥有指针)。

我的问题是:创建

std::make_shared
的 Qt 类似物不是很方便吗?像这样,创建
QSharedPtr
:

namespace Qt
{
  template<class T, class... Args>
  QSharedPointer<T> make_shared(Args&&... args)
  {
    return QSharedPointer<T>(new T(std::forward<Args>(args)...));
  }
}

或者像这样,用于创建

QPointer

namespace Qt
{
  template<class T, class... Args>
  QPointer<T> make_ptr(Args&&... args)
  {
     return QPointer<T>(new T(std::forward<Args>(args)...));
  }
}

它可以像这样使用:

auto pCancelButton = Qt::make_ptr<QPushButton>("Cancel", this);

这种方法有什么注意事项吗?这种方法有任何公开的用法吗?

更新我声称只要

Qt::make_ptr
有用,
QPointer
就有用,因为它将隐藏
new
运算符并确保仅对继承
new
的东西调用
QObject
。 Qt 用户做了很多
new
,但通过这种方式我们可以确定
new
仅在 Qt 上下文中使用。对于这个想法有什么争论吗?

c++ qt c++11 smart-pointers
1个回答
19
投票

make_shared
等功能严格依赖于完美转发功能,该功能自C++11以来才可用并引入了通用(转发)引用。话虽如此,如果没有完美的转发,使用这个功能可能效率很低。 Qt 比最近的 C++ 标准要老得多,因此直到 Qt 5.1 才可用(就像以前一样,您必须使用 Qt 的内部预处理宏,如
SIGNAL
SLOT
来建立连接)。

Qt 5.1 已经提供了自己的实现来为 QSharedPointer制作智能指针。

静态

create
成员函数可以按如下方式使用:

auto ptr = QSharedPointer<QPushButton>::create("Cancel", this);

但请注意描述:

注意:此函数仅适用于支持任意数量参数完美转发的C++11编译器。如果编译器不支持必要的 C++11 功能,则必须使用调用默认构造函数的重载。

使用

make_shared
create
函数比直接调用构造函数并使用
new
分配内存有两大优点:

  1. 特殊的完美转发函数可以在单个系统调用中为存储对象引用计数器分配内存。

  2. 内存分配与调用上下文分离,因此可以避免在构造另一个对象时引发异常时发生内存泄漏。函数调用(编译器可以自由选择参数的计算顺序)。考虑:

     foo(QSharedPointer<QPushButton>(new QPushButton("Cancel", this)), MayThrow());
    

也就是说,如果编译器首先执行

new QPushButton("Cancel", this)
表达式,然后在调用
MayThrow()
的构造函数之前调用
QSharedPointer
函数,那么如果
MayThrow()
函数抛出异常,则可能会泄漏内存。

© www.soinside.com 2019 - 2024. All rights reserved.