Make QSharedPointer without custom deleters call the correct destructor
Where "correct" is defined by what std::shared_ptr does as well as what
happens when an intermediate QSharedPointer of the exact type of the
constructor behaves
That is,
QSharedPointer<X> ptr(new Y);
Behaves like
QSharedPointer<X> ptr;
{ QSharedPointer<Y> tmp(new Y); ptr = tmp; }
Change-Id: Id75834dab9ed466e94c7ffff14455d445f72592b
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
bb10
parent
a7e3c17e75
commit
e22a230a03
|
|
@ -447,6 +447,11 @@
|
|||
Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
|
||||
becomes managed by this QSharedPointer and must not be passed to
|
||||
another QSharedPointer object or deleted outside this object.
|
||||
|
||||
Since Qt 5.8, when the last reference to this QSharedPointer gets
|
||||
destroyed, \a ptr will be deleted by calling \c X's destructor (even if \c
|
||||
X is not the same as QSharedPointer's template parameter \c T). Previously,
|
||||
the destructor for \c T was called.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
@ -477,6 +482,9 @@
|
|||
}
|
||||
\endcode
|
||||
|
||||
Note that the custom deleter function will be called with a pointer to type
|
||||
\c X, even if the QSharedPointer template parameter \c T is not the same.
|
||||
|
||||
It is also possible to specify a member function directly, as in:
|
||||
\code
|
||||
QSharedPointer<MyObject> obj =
|
||||
|
|
|
|||
|
|
@ -518,15 +518,15 @@ private:
|
|||
|
||||
inline void enableSharedFromThis(...) {}
|
||||
|
||||
template <typename Deleter>
|
||||
inline void internalConstruct(T *ptr, Deleter deleter)
|
||||
template <typename X, typename Deleter>
|
||||
inline void internalConstruct(X *ptr, Deleter deleter)
|
||||
{
|
||||
if (!ptr) {
|
||||
d = Q_NULLPTR;
|
||||
return;
|
||||
}
|
||||
|
||||
typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<T, Deleter> Private;
|
||||
typedef QtSharedPointer::ExternalRefCountWithCustomDeleter<X, Deleter> Private;
|
||||
# ifdef QT_SHAREDPOINTER_TRACK_POINTERS
|
||||
typename Private::DestroyerFn actualDeleter = &Private::safetyCheckDeleter;
|
||||
# else
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ private slots:
|
|||
void useOfForwardDeclared();
|
||||
void memoryManagement();
|
||||
void dropLastReferenceOfForwardDeclared();
|
||||
void nonVirtualDestructors();
|
||||
void lock();
|
||||
void downCast();
|
||||
void functionCallDownCast();
|
||||
|
|
@ -603,6 +604,56 @@ void tst_QSharedPointer::dropLastReferenceOfForwardDeclared()
|
|||
QCOMPARE(forwardDeclaredDestructorRunCount, 1);
|
||||
}
|
||||
|
||||
// NVD for "non-virtual destructor"
|
||||
struct NVDData
|
||||
{
|
||||
static int destructorCounter;
|
||||
~NVDData() { ++destructorCounter; }
|
||||
|
||||
int dummy;
|
||||
};
|
||||
int NVDData::destructorCounter;
|
||||
|
||||
struct NVDDerivedData : NVDData
|
||||
{
|
||||
static int destructorCounter;
|
||||
~NVDDerivedData() { ++destructorCounter; }
|
||||
};
|
||||
int NVDDerivedData::destructorCounter;
|
||||
|
||||
void tst_QSharedPointer::nonVirtualDestructors()
|
||||
{
|
||||
NVDData::destructorCounter = NVDDerivedData::destructorCounter = 0;
|
||||
{
|
||||
QSharedPointer<NVDData> ptr(new NVDData);
|
||||
}
|
||||
QCOMPARE(NVDData::destructorCounter, 1);
|
||||
QCOMPARE(NVDDerivedData::destructorCounter, 0);
|
||||
|
||||
NVDData::destructorCounter = NVDDerivedData::destructorCounter = 0;
|
||||
{
|
||||
QSharedPointer<NVDDerivedData> ptr(new NVDDerivedData);
|
||||
}
|
||||
QCOMPARE(NVDData::destructorCounter, 1);
|
||||
QCOMPARE(NVDDerivedData::destructorCounter, 1);
|
||||
|
||||
NVDData::destructorCounter = NVDDerivedData::destructorCounter = 0;
|
||||
{
|
||||
QSharedPointer<NVDData> bptr;
|
||||
QSharedPointer<NVDDerivedData> ptr(new NVDDerivedData);
|
||||
bptr = ptr;
|
||||
}
|
||||
QCOMPARE(NVDData::destructorCounter, 1);
|
||||
QCOMPARE(NVDDerivedData::destructorCounter, 1);
|
||||
|
||||
NVDData::destructorCounter = NVDDerivedData::destructorCounter = 0;
|
||||
{
|
||||
QSharedPointer<NVDData> ptr(new NVDDerivedData);
|
||||
}
|
||||
QCOMPARE(NVDData::destructorCounter, 1);
|
||||
QCOMPARE(NVDDerivedData::destructorCounter, 1);
|
||||
}
|
||||
|
||||
void tst_QSharedPointer::lock()
|
||||
{
|
||||
QSharedPointer<int> sp = QSharedPointer<int>::create();
|
||||
|
|
@ -1529,6 +1580,33 @@ void tst_QSharedPointer::customDeleter()
|
|||
QCOMPARE(refcount, 2);
|
||||
safetyCheck();
|
||||
|
||||
CustomDeleter<NVDData> nvdeleter;
|
||||
nvdeleter.callCount = 0;
|
||||
{
|
||||
QSharedPointer<NVDData> ptr(new NVDData, nvdeleter);
|
||||
}
|
||||
QCOMPARE(nvdeleter.callCount, 1);
|
||||
safetyCheck();
|
||||
|
||||
CustomDeleter<NVDDerivedData> nvderiveddeleter;
|
||||
nvdeleter.callCount = 0;
|
||||
nvderiveddeleter.callCount = 0;
|
||||
{
|
||||
QSharedPointer<NVDDerivedData> ptr(new NVDDerivedData, nvderiveddeleter);
|
||||
}
|
||||
QCOMPARE(nvdeleter.callCount, 0);
|
||||
QCOMPARE(nvderiveddeleter.callCount, 1);
|
||||
safetyCheck();
|
||||
|
||||
nvdeleter.callCount = 0;
|
||||
nvderiveddeleter.callCount = 0;
|
||||
{
|
||||
QSharedPointer<NVDData> ptr(new NVDDerivedData, nvderiveddeleter);
|
||||
}
|
||||
QCOMPARE(nvdeleter.callCount, 0);
|
||||
QCOMPARE(nvderiveddeleter.callCount, 1);
|
||||
safetyCheck();
|
||||
|
||||
// a custom deleter with a different pointer parameter
|
||||
{
|
||||
QSharedPointer<char> ptr(static_cast<char *>(malloc(1)), free);
|
||||
|
|
|
|||
Loading…
Reference in New Issue