[Development] What's the status of a moved-from object?
Mutz, Marc
marc at kdab.com
Tue May 21 10:27:56 CEST 2019
Hi Lars,
There is a fine line between a proper partially-formed state and
basically folding std::optional into every value class.
The former is a compile-time state. It is not observable at runtime,
because any code which would observe a difference invokes UB. This is
the same principle as C++11 data races, btw: Sequential Consistency for
Data-Race-Free Programs.
The latter is a run-time property. As such, it will cost cpu cycles,
death by a thousand paper cuts, sure, but cost. The cost is not
necessarily in the extra branch, it's mostly in impairng the compiler's
ability to optimize on the impossiblity of UB, which is important for,
amongst other things, dead code removal. And while the partially-formed
state can be extended to non-pimpled classes easily:
class QRect {
int x, y, w, h;
public:
QRect() = default;
};
QRect r; // partially-formed
r.x(); // compilers _already_ warn about this
QRect r = {}; // zero-initialized
QRect::isValid() has always been weird API, since it needs to reserve
some valid, but non-normalized, values (remember, there's
QRect::normalize()), to implement an optional absence of a rect. That
should be modelled by optional<QRect>, not by QRect itself.
To summarize: the partially-formed state is a compile-time only concept
with no runtime cost and is applicable to all C++ types (from int over
structs to Qt classes). It is consistent across all types, improves
performance as well as readability of source code, and can be detected
both at runtime (with asserts) and compile time (with static analysis).
A d == nullptr state as a valid value is a runtime property, has
associated costs, and makes source code harder to understand.
It is, however, be an acceptable stop-gap measure, and here a compromise
may emerge, for keeping old code working while preparing for a
fully-implemented partially-formed state. This would mean we do assign
meaning to a nullptr d consistent with the documented default value in
Qt 5, but deprecate the use of the default ctor for establishing said
value in the docs and warn about the use of a default-constructed object
other than for destruction and assignment at runtime, even in release
mode. In Qt 7, we then crash, as we do for some moved-from objects
already.
Would that find your approval?
Thanks,
Marc
More information about the Development
mailing list