QPen: add move constructor
After this change, the relation between copy/move constructor calls in QtGui is something like 40/16. A moved-from QPen can only be copied, assigned-to or else destroyed. This required adding a nullptr check to the copy ctor and the dtor and rewriting copy assignment (which used non-nullptr-safe qAtomicAssign) in terms of copy construction and swapping. Extensive tests included. They are implemented such that they work in C++98 as well as C++11 mode, but they naturally test move semantics only in a C++11 build. Change-Id: If68f37c10b8eeefb2478cbae386cd2e38b4f6e19 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
98d7d4c1e5
commit
db8167c224
|
|
@ -327,17 +327,29 @@ QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c,
|
|||
QPen::QPen(const QPen &p)
|
||||
{
|
||||
d = p.d;
|
||||
d->ref.ref();
|
||||
if (d)
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn QPen::QPen(QPen &&pen)
|
||||
\since 5.4
|
||||
|
||||
Constructs a pen that is moved from the given \a pen.
|
||||
|
||||
The moved-from pen can only be assigned to, copied, or
|
||||
destroyed. Any other operation (prior to assignment) leads to
|
||||
undefined behavior.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Destroys the pen.
|
||||
*/
|
||||
|
||||
QPen::~QPen()
|
||||
{
|
||||
if (!d->ref.deref())
|
||||
if (d && !d->ref.deref())
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
|
@ -373,7 +385,7 @@ void QPen::detach()
|
|||
|
||||
QPen &QPen::operator=(const QPen &p)
|
||||
{
|
||||
qAtomicAssign(d, p.d);
|
||||
QPen(p).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ public:
|
|||
|
||||
QPen &operator=(const QPen &pen);
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
inline QPen(QPen &&other)
|
||||
: d(other.d) { other.d = 0; }
|
||||
inline QPen &operator=(QPen &&other)
|
||||
{ qSwap(d, other.d); return *this; }
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ public:
|
|||
private slots:
|
||||
void getSetCheck();
|
||||
void swap();
|
||||
void move();
|
||||
void move_assign();
|
||||
void operator_eq_eq();
|
||||
void operator_eq_eq_data();
|
||||
|
||||
|
|
@ -101,6 +103,57 @@ void tst_QPen::swap()
|
|||
QCOMPARE(p2.color(), QColor(Qt::black));
|
||||
}
|
||||
|
||||
void tst_QPen::move()
|
||||
{
|
||||
QPen p1(Qt::black);
|
||||
|
||||
// check that moving does the right thing:
|
||||
QPen p2 = qMove(p1); // could be move or copy construction, so don't check p1's state
|
||||
QCOMPARE(p2.color(), QColor(Qt::black));
|
||||
|
||||
// this, executed ehre, would crash:
|
||||
// QVERIFY(p1.style() != Qt::NoPen);
|
||||
|
||||
// check that moved-from QPen p1 can still be safely copied:
|
||||
const QPen p3 = p1;
|
||||
|
||||
// check that moved-from QPen p1 can still be safely assigned to:
|
||||
const QPen p4(Qt::yellow);
|
||||
p1 = p4;
|
||||
QCOMPARE(p1.color(), QColor(Qt::yellow));
|
||||
|
||||
// check that moved-from QPens p2, p3 can still be safely destroyed:
|
||||
QPen p5 = qMove(p2);
|
||||
|
||||
// intentionally no more statements beyond this point
|
||||
}
|
||||
|
||||
void tst_QPen::move_assign()
|
||||
{
|
||||
QPen p1(Qt::black), p2(Qt::white);
|
||||
|
||||
// check that moving does the right thing:
|
||||
p2 = qMove(p1); // could be move or copy assignment, so don't check p1's state
|
||||
QCOMPARE(p2.color(), QColor(Qt::black));
|
||||
|
||||
// check that move-assigned-from QPen p1 can still be used, albeit
|
||||
// with undocumented state (it's p2's original state):
|
||||
QVERIFY(p1.style() != Qt::NoPen);
|
||||
|
||||
// check that moved-from QPen p1 can still be safely copied:
|
||||
const QPen p3 = p1;
|
||||
|
||||
// check that moved-from QPen p1 can still be safely assigned to:
|
||||
const QPen p4(Qt::yellow);
|
||||
p1 = p4;
|
||||
QCOMPARE(p1.color(), QColor(Qt::yellow));
|
||||
|
||||
// check that moved-from QPens p2, p3 can still be safely destroyed:
|
||||
QPen p5;
|
||||
p5 = qMove(p2);
|
||||
|
||||
// intentionally no more statements beyond this point
|
||||
}
|
||||
|
||||
tst_QPen::tst_QPen()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue