summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qsharedpointer.cpp8
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h6
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp78
3 files changed, 89 insertions, 3 deletions
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index f420c6237b..c369ff8697 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -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 =
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index b9b29e926d..bbac2d0327 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -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
diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
index f48e81ed91..7998f7b7fd 100644
--- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
@@ -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);