Ho pensato che QML supportasse le funzioni lambda a causa del supporto JavaScript delle funzioni anonime e del fatto che le funzioni sono oggetti di prima classe, ma non funzionano come mi aspettavo. Prendete questo codice:QML: la funzione Lambda funziona in modo imprevisto
Item {
property var items: []
function handler(item) {
console.log(item);
}
Component.onCompleted: {
for (var i = 0; i < 3; ++i) {
var item = someObj.createObject();
item.someValueChanged.connect(function() {
handler(item); });
items.push(item);
console.log("Adding:", item);
}
}
Component {
id: someObj
Item {
property bool someValue: false
Timer {
running: true
onTriggered: {
parent.someValue = true;
}
}
}
}
}
Sto cercando di utilizzare il lambda function() { handler(item); }
in modo che quando il segnale viene emesso someObj::someValueChanged
l'elemento che emette è passato alla funzione handler(item)
.
I presume che ogni ciclo creerebbe una nuova istanza del lambda e che il riferimento item
porterebbe il riferimento del someObj
istanza creata in quel ciclo (cioè item
sarebbe catturato dal lambda). Ma questo non sembra essere il caso come l'output è:
qml: Adding: QQuickItem_QML_1(0x2442aa0)
qml: Adding: QQuickItem_QML_1(0x2443c00)
qml: Adding: QQuickItem_QML_1(0x2445370)
qml: QQuickItem_QML_1(0x2445370)
qml: QQuickItem_QML_1(0x2445370)
qml: QQuickItem_QML_1(0x2445370)
Come si può vedere, sia l'intera funzione viene sostituito ad ogni ciclo o solo il riferimento item
, in modo che alla fine l'ultimo creato solo someObj
è riferito a. Qualcuno può spiegarmi perché i lambda (se è persino quello che è) non funzionano come mi aspetto? E questo è un problema di QML o di JavaScript generico?
Ah, questo ha senso (per JS comunque). Grazie! – cmannett85
@ cmannett85 - cosa succederebbe in C++ se si tenta di eseguire un lambda in ritardo, facendo riferimento ai locals di una funzione che è andata oltre lo scopo? Il caso migliore se fosse in pila all'inizio e lo stack non è andato a quella profondità in seguito e quella memoria non viene sovrascritta, potrebbe funzionare, ma molto probabilmente andrà in crash. – dtech
Vero tranne che in C++ è possibile specificare cosa viene catturato _e come_. Qualcosa che JS non supporta (almeno la versione utilizzata da QtQuick). – cmannett85