[Interest] Qt::MakePointer for creating QPointer as std::make_shared for creating std::shared_ptr

Mikhail Matrosov mikhail.matrosov at gmail.com
Fri Oct 17 22:43:05 CEST 2014


I got another thought on the subject. We ultimately have three allocation
options:
1. Create QObject on the stack
2. Create QObject on the heap with a parent
3. Create QObject on the heap without a parent (null parent)

In first two options object is deleted automatically (by going out of scope
or when parent is deleted). That's why they might be considered _safe_. In
third option however, we should manually delete the object or assign it a
parent. We may forgot or fail to do this, that's why it might be considered
_unsafe_.

I suggest to use my object creating wrapper aka Qt::MakeSomething() for the
second option to emphasize it is safe, while raw new and delete should be
used for the third option to emphasize it is unsafe. So instead of
Qt::MakePointer() I suggest to use Qt::MakeChild(), with the only
difference is that raw pointer instead of QPointer is returned:

namespace Qt
{
  template<class T, class... Args>
  T* MakeChild(Args&&... args)
  {
    T* pObject = new T(std::forward<Args>(args)...);
    Q_ASSERT(pObject->parent() != nullptr);
    return pObject;
  }
}

I suppose that Qt::MakeChild() with assertion removed in release build is
potentially a zero overhead comparing with raw new. And when we see raw new
in the code we now know that created object should be necessarily handled
after creation (be assigned with parent or be manually deleted). What do
you think on this approach?



-----
Best regards, Mikhail Matrosov

2014-10-17 11:44 GMT+04:00 Koehne Kai <Kai.Koehne at theqtcompany.com>:

>
>
> > -----Original Message-----
> > From: interest-bounces+kai.koehne=theqtcompany.com at qt-project.org
> > [mailto:interest-bounces+kai.koehne=theqtcompany.com at qt-project.org]
> > On Behalf Of Mikhail Matrosov
> > Sent: Wednesday, October 15, 2014 11:57 PM
> > To: interest at qt-project.org
> > Subject: [Interest] Qt::MakePointer for creating QPointer as
> > std::make_shared for creating std::shared_ptr
> >
> > Hello!
> >
> > In modern C++ there is almost no need to use raw new and delete. As
> Bjarne
> > Stroustrup is saying in his “A Tour of C++”: “Avoid ‘‘naked’’ new and
> delete
> > operations; §4.2.2.”. We use standard containers and smart pointers for
> that,
> > with std::make_shared and std::make_unique functions for smart pointers
> > creation.
>
> It's probably worth thinking about _why_ Stroustrup et al advocate not
> using 'naked' new/delete. The original proposal for unique_ptr lists a
> couple of reasons (
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt)
>
> 1. Consistency
>
> 'It will be possible to teach users "never say new/delete/new[]/delete[]"
> without disclaimers.' (and therefore advocate a style where the ownership
> model of a heap allocation is always explicit).
>
> 2. Less verbosity
>
>   auto up = make_unique<LongTypeName>
>
>  is just less noise than
>
>   unique_ptr<LongTypeName> up(new LongTypeName(args))
>
> 3. Exception safety
>
> More specifically, avoiding leaking if the constructor throws due to
> unspecified-evaluation-order in expressions like "foo(unique_ptr<X>(new X),
> unique_ptr<Y>(new Y))".
>
>
> Let's see how these apply to your MakePointer:
>
> 1. Consistency
>
> That's apparently your motivation. Anyhow, note that QPointer is - in
> contrast to std::unique_ptr, _not_ a free ride. It requires bookkeeping in
> t the target object, and also atomic operations on every access. So I'd
> strongly advocate you don't want to use QPointer for apps where performance
> matters.
>
> (std::unique_ptr also isn't completely free btw either in debug builds,
> because it tends to generate lots of additional debug symbols. But that's
> another discussion ...)
>
> Also, as Reinhardt Behm has pointed out, there are sometimes valid reasons
> to have a QObject pointer without a parent at construction time. So you
> might even not get away if removing 'naked' news completely.
>
> 2. Verbosity
>
> That's only valid if you'd use a QPointer in the first place.
>
> 3. Exception safety
>
> Whether exception safety is important to you, and you allow throwing of
> exceptions in any constructors, depends obviously on your code. Qt doesn't
> use exceptions itself though, and is also only exception safe to a limited
> degree ....
>
> > In Qt we also have QSharedPointer and QSharedPointer<T>::create(…)
> > method. But we don’t use smart pointers in Qt much, due to parent-driven
> > memory model. And most of QObjects are created with raw new operations.
> >
> > Maybe it is a proper thing to add some C++14-style wrapper for creating
> > QObjects like this:
> >
> > 1.
> >       namespace Qt <http://qt-project.org/doc/Qt.html>
> > 2.
> >       {
> > 3.
> >         template<class T, class... Args>
> > 4.
> >         QPointer <http://qt-project.org/doc/QPointer.html> <T>
> > MakePointer(Args&&... args)
> > 5.
> >         {
> > 6.
> >           T* pObject = new T(std::forward<Args>(args)...);
> > 7.
> >           Q_ASSERT(pObject->parent() != nullptr);
> > 8.
> >           return pObject;
> > 9.
> >         }
> > 10.
> >       }
> >
> > Now, one can safely call Qt::MakePointer to create a QObject and be sure
> it
> > will not leak due to an assertion for an existing parent. And it will
> free all the
> > calling code from raw newoperations. One can always use raw delete to
> > destroy the object, but he does not have to. And even if he will, it
> will not
> > lead to dangling pointers problem since QPointer is automatically set to
> null in
> > this case.
> >
> > I’m planning to use this approach in my code. Do you think it is
> relevant? Are
> > there any drawbacks?
>
> Drawbacks are the additional price you pay for QPointer, see above.
>
> > PS This is a cross-post of my question from Qt forums: http://qt-
> > project.org/forums/viewthread/48541, where SGaist <http://qt-
> > project.org/mebmer/39728>  suggested me to post here.
> >
> >
> > -----
> > Best regards, Mikhail Matrosov
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20141018/c6cfa652/attachment.html>


More information about the Interest mailing list