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

时间:2014-10-10 08:40:05

标签: c++ qt c++11 smart-pointers

正如Bjarne Stroustrup的“C ++之旅”中所述,并且作为已知的C ++ 14实践,应该避免代码中的裸newdelete。标准库提供std::make_sharedstd::make_unique,用于创建智能指针以立即存储已分配的对象。

但是,不可能将这些例程用于非标准智能指针,例如Qt。 Qt有自己的内存管理模型(带父项),但也提供智能指针类,如QSharedPointerQPointer(尽管后者实际上并不是拥有指针)。

我的问题是:创建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上下文。关于这个想法的任何争论?

1 个答案:

答案 0 :(得分:12)

make_shared等功能严格依赖于完美转发功能,该功能仅在C ++ 11和通用(转发)引用。话虽如此,如果没有完美转发,使用此功能可能效率低下。 Qt比最近的C ++标准要老,因此直到Qt 5.1才可用(就像以前你必须使用Qt的内部预处理宏,如SIGNALSLOT来建立连接)。 / p>

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

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

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

但请注意说明:

  

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

使用make_sharedcreate函数有两个主要优点,而不是直接使用new分配内存来调用构造函数:

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

  2. 内存分配与调用上下文分离,因此如果在构建另一个对象时抛出异常,则可以避免内存泄漏。函数调用(编译器可以自由选择评估参数的顺序)。考虑:

    foo(QSharedPointer<QPushButton>(new QPushButton("Cancel", this)), MayThrow());
    
  3. 也就是说,如果编译器首先执行new QPushButton("Cancel", this)表达式,然后在调用MayThrow()的构造函数之前调用QSharedPointer函数,则MayThrow()可能会泄漏内存函数抛出异常。