QML 值类型
and
QML 序列类型
are necessarily passed by value. In contrast to
QML 对象类型
they have no identity of themselves, but can only be accessed as properties of other objects or values, or as values returned from methods. Each such access implicitly creates a copy. Yet, in JavaScript everything is an object. There is no such concept as a value type in JavaScript. For example, if you execute
font.bold = true
in JavaScript, we expect the
bold
property of
font
to be set, no matter what
font
is. But consider the following code snippet:
import QtQuick Text { onSomethingHappened: font.bold = true }
In this case we know that
font
is a value type. Accessing it creates a local copy by calling the getter of a
Q_PROPERTY
. We can then set the
bold
property on it, but that would usually only affect the copy, not the original
Q_PROPERTY
.
To overcome this problem, QML offers the concept of references. When you retrieve an instance of a value or sequence type from a property, the QML engine remembers the property along with the value itself. If the value is modified, it is written back to the property. This produces the illusion of an object with separate identity and makes the above case, along with many others, just work.
This can be rather expensive, though. If a sequence is exposed as a Q_PROPERTY , accessing any value in the sequence by index will cause the whole sequence data to be read from the property. From this sequence data, a single element is then retrieved. Similarly, modifying any value in the sequence causes the sequence data to be read. Then the modification is performed and the modified sequence is be written back to the property. A read operation can be relatively cheap if the type in question is implicitly shared. A modification always incurs at least one deep copy.
If you return an instance of a sequence or value type from a Q_INVOKABLE function you avoid such overhead. Return values are not attached to any property and won't be written back.
Sequences of object types are passed as QQmlListProperty 在默认情况下。 QQmlListProperty is not an actual container, but only a view, or reference, to some sequential storage. Therefore, { QQmlListProperty } is not affected by this effect. You can, however, register other sequence types for objects using QML_SEQUENTIAL_CONTAINER . Those will be affected.