Initialization of QSharedDataPointer's for empty objects (i.e. Foo::Foo(void))
Thiago Macieira
thiago at kde.org
Mon Apr 29 23:16:29 BST 2013
On segunda-feira, 29 de abril de 2013 21.52.37, Milian Wolff wrote:
> I.e.: In the ctors that construct an "empty" object do not call "new
> Private" but instead (re-)use a static shared empty object created on the
> stack - see shared_empty and shared_null in qstring.{cpp,h}.
You probably did not mean what you said: you do not want something allocated
on the stack. You want a global. Like QString :-)
To be *really* like QString, you want your private to be POD. That means you
cannot derive from QSharedData, you cannot use QAtomicInt, QString or
QByteArray. That may be taking it a bit too far.
If your private class is not POD, you should use a K/Q_GLOBAL_STATIC instead
to hold your private. Examples:
corelib/mimetypes/qmimedatabase.cpp:Q_GLOBAL_STATIC(QMimeDatabasePrivate,
staticQMimeDatabase)
corelib/tools/qlocale_win.cpp:Q_GLOBAL_STATIC(QSystemLocalePrivate,
systemLocalePrivate)
gui/text/qfontdatabase.cpp:Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb)
network/access/qabstractnetworkcache.cpp:Q_GLOBAL_STATIC(QNetworkCacheMetaDataPrivate,
metadata_shared_invalid)
plugins/bearer/qnetworksession_impl.cpp:Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate,
sessionManager);
sql/kernel/qsqlquery.cpp:Q_GLOBAL_STATIC_WITH_ARGS(QSqlQueryPrivate,
nullQueryPrivate, (0))
> I do wonder though why QString has both, a shared_empty and a shared_null
> object. A single one should suffice for most objects, no?
QString().isNull() == true
QString("").isNull() == false
> Does anyone have any experience with this? Are there any pitfalls or
> downsides to the approach taken by QString? I also thought about not
> initializing the QSaredDataPointer at all but that would require a lot of
> additional code when its being used to ensure its only accessed when it is
> initialized. I think the pattern applied in QString is much nicer in that
> regard.
It is, but the pattern of having a null d pointer also exists elsewhere in Qt.
For example, in QUrl, it's implemented manually. But there are also a few
examples of doing that with QSharedDataPointer.
Take a look at QNetworkProxy or QUrlQuery:
template<> void QSharedDataPointer<QNetworkProxyPrivate>::detach()
{
if (d && d->ref.load() == 1)
return;
QNetworkProxyPrivate *x = (d ? new QNetworkProxyPrivate(*d)
: new QNetworkProxyPrivate);
x->ref.ref();
if (d && !d->ref.deref())
delete d;
d = x;
}
And then:
QNetworkProxy::ProxyType QNetworkProxy::type() const
{
return d ? d->type : DefaultProxy;
}
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20130429/e9cd2aef/attachment.sig>
More information about the kde-core-devel
mailing list