diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp index a3c6a9debf..bd2be0fc7a 100644 --- a/src/sql/kernel/qsqlrecord.cpp +++ b/src/sql/kernel/qsqlrecord.cpp @@ -88,6 +88,37 @@ QSqlRecord::QSqlRecord(const QSqlRecord& other) d->ref.ref(); } +/*! + \fn QSqlRecord::QSqlRecord(QSqlRecord &&other) + \since 6.6 + + Move-constructs a new QSqlRecord from \a other. + + \note The moved-from object \a other is placed in a partially-formed state, + in which the only valid operations are destruction and assignment of a new + value. +*/ + +/*! + \fn QSqlRecord &QSqlRecord::operator=(QSqlRecord &&other) + \since 6.6 + + Move-assigns \a other to this QSqlRecord instance. + + \note The moved-from object \a other is placed in a partially-formed state, + in which the only valid operations are destruction and assignment of a new + value. +*/ + +/*! + \fn void QSqlRecord::swap(QSqlRecord &other) + \since 6.6 + + Swaps SQL record \a other with this SQL record. This operation is very fast + and never fails. +*/ + + /*! Sets the record equal to \a other. @@ -97,7 +128,7 @@ QSqlRecord::QSqlRecord(const QSqlRecord& other) QSqlRecord& QSqlRecord::operator=(const QSqlRecord& other) { - qAtomicAssign(d, other.d); + QSqlRecord(other).swap(*this); return *this; } @@ -107,7 +138,7 @@ QSqlRecord& QSqlRecord::operator=(const QSqlRecord& other) QSqlRecord::~QSqlRecord() { - if (!d->ref.deref()) + if (d && !d->ref.deref()) delete d; } diff --git a/src/sql/kernel/qsqlrecord.h b/src/sql/kernel/qsqlrecord.h index cb88f1c62e..76e6ee982d 100644 --- a/src/sql/kernel/qsqlrecord.h +++ b/src/sql/kernel/qsqlrecord.h @@ -19,9 +19,14 @@ class Q_SQL_EXPORT QSqlRecord public: QSqlRecord(); QSqlRecord(const QSqlRecord& other); + QSqlRecord(QSqlRecord &&other) noexcept + : d{std::exchange(other.d, nullptr)} {} QSqlRecord& operator=(const QSqlRecord& other); + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSqlRecord) ~QSqlRecord(); + void swap(QSqlRecord &other) noexcept { qt_ptr_swap(d, other.d); } + bool operator==(const QSqlRecord &other) const; inline bool operator!=(const QSqlRecord &other) const { return !operator==(other); } diff --git a/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp b/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp index 4d41c6aaa9..2c9eedd8d4 100644 --- a/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp +++ b/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp @@ -40,6 +40,7 @@ private slots: void clearValues(); void clear(); void append(); + void moveSemantics(); private: std::unique_ptr rec; @@ -449,5 +450,24 @@ void tst_QSqlRecord::value() QCOMPARE(rec2.value("string").toString(), QLatin1String("Harry")); } +void tst_QSqlRecord::moveSemantics() +{ + QSqlRecord rec, empty; + rec.append(QSqlField("string", QMetaType(QMetaType::QString))); + rec.setValue("string", "Harry"); + auto moved = std::move(rec); + // `rec` is not partially-formed + + // moving transfers state: + QCOMPARE(moved.value("string").toString(), QLatin1String("Harry")); + + // moved-from objects can be assigned-to: + rec = empty; + QVERIFY(rec.value("string").isNull()); + + // moved-from object can be destroyed: + moved = std::move(rec); +} + QTEST_MAIN(tst_QSqlRecord) #include "tst_qsqlrecord.moc"