Ho una funzione in una classe che definisce un lambda e lo memorizza in una variabile statica locale:Quando è "questo" catturato in una lambda?
class A
{
public:
void call_print()
{
static auto const print_func = [this] {
print();
};
print_func();
};
virtual void print()
{
std::cout << "A::print()\n";
}
};
class B : public A
{
public:
virtual void print() override
{
std::cout << "B::print()\n";
}
};
Ho anche eseguire il seguente test:
int main()
{
A a;
B b;
a.call_print();
b.call_print();
}
Quello che mi aspetto di stampare è:
A::print()
B::print()
Ma quello che proprio mi piace è:
A::print()
A::print()
(indirizzo stesso oggetto viene stampato anche con ciascuno)
Ho il sospetto che questo è dovuto alla cattura this
. Supponevo che avrebbe catturato il valore di this
quando è stato chiamato, tuttavia sembra essere catturato nel momento in cui viene definita la lambda.
Qualcuno potrebbe spiegare la semantica delle catture lambda? Quando vengono effettivamente forniti alla funzione? È lo stesso per tutti i tipi di cattura, oppure è this
un caso speciale? La rimozione di static
risolve il problema, tuttavia nel mio codice di produzione sto effettivamente memorizzando il lambda in un oggetto leggermente più pesante che rappresenta uno slot a cui inserisco successivamente un segnale.
Potrebbe valere la pena di aggiungere che questo rappresenta in realtà uno stile di programmazione molto pericoloso, dal momento che se 'a' viene cancellato, le future chiamate a' call_print' invocheranno un comportamento indefinito e molto probabilmente un crash. – Xirema
@Xirema Questo è vero, ma non penso che questo sia il comportamento che sta cercando di ottenere. –
Capisco la semantica di 'static', quello che sto cercando di capire è se il lambda" promette "di catturare' this' * tardi *, o se è catturato * giusto allora *. Hai affrontato questo nella tua risposta, però. Volevo che il contenitore per il lambda fosse statico, ma non le catture. Speravo che fossero separati tra definizione e invocazione. –