Lambda 襨螞ĺźć˜Żĺœ¨ C++11 ä¸ĺŠ ĺ…Ľçš„ C++ ç‰šć€§ă€‚ĺœ¨čż™çŻ‡ć–‡çŤ ä¸ćˆ‘äťŹĺ°†çœ‹ĺˆ°ĺŚ‚ä˝•ç”¨ Lambda 襨螞ĺźćĽçŽ€ĺŒ– Qt 䝣ç 。Lambda ĺžˆĺźşĺ¤§ďźŒä˝†äšŸčŚĺ°ĺżƒĺŽƒĺ¸ŚćĽçš„é™ˇé˜ąă€‚
Lambda 襨螞ĺźć˜Żĺœ¨ćŸä¸Şĺ‡˝ć•°ä¸ç›´ćŽĽĺŽšäš‰çš„ĺŒżĺĺ‡˝ć•°ă€‚ĺŽƒĺŻäťĽç”¨äşŽäťťä˝•需čŚäź é€’ĺ‡˝ć•°ćŒ‡é’ˆçš„ĺœ°ć–šă€‚
Lambda 襨螞ĺźçš„čŻćł•匂下
[莡ĺ–ĺ˜é‡](ĺ‚ć•°) {     lambda 䝣ç }
çŽ°ĺœ¨ĺ…ˆĺż˝ç•Ľ â€œčŽˇĺ–ĺ˜é‡â€ čż™éƒ¨ĺˆ†ă€‚ä¸‹é˘ć˜Żä¸€ä¸ŞçŽ€ĺ•çš„ LambdaďźŒç”¨äşŽé€’ĺ˘žä¸€ä¸Şć•°ďźš
[](int value) {     return value + 1; }
ćˆ‘äťŹĺŻäťĽćŠŠčż™ä¸Ş Lambda 用于ĺƒÂ std::transform()Â čż™ć ˇçš„ĺ‡˝ć•°ďźŒćĽä¸ş vector çš„ćŻä¸€ä¸Şĺ…ƒç´ 增借
#include #include #include int main() {     std::vector vect = { 1, 2, 3 };     std::transform(vect.begin(), vect.end(), vect.begin(),                    [](int value) { return value + 1; });    for(int value : vect) { std::cout
打ĺ°çť“ćžœďźš
2 3 4
Lambda 襨螞ĺźĺŻäťĽé€ščż‡ â€œčŽˇĺ–†ćĽä˝żç”¨ĺ˝“ĺ‰ä˝œç”¨ĺŸŸä¸çš„ĺ˜é‡ă€‚下é˘ć˜Żç”¨ Lambda ćĽĺŻš vector ćą‚ĺ’Œçš„ä¸€ä¸Şç¤şäž‹ă€‚
std::vector vect = { 1, 2, 3 }; int sum = 0; std::for_each(vect.begin(), vect.end(), [&sum](int value) {     sum += value; });
ä˝ ĺŻäťĽçœ‹ĺˆ°ďźŒćˆ‘䝏莡ĺ–äş†ćœŹĺœ°ĺ˜é‡ sumďźŒć‰€äťĽĺŻäťĽĺœ¨ Lambda ĺ†…éƒ¨ä˝żç”¨ĺŽƒă€‚sum ĺŠ äş†ĺ‰çź€ &ďźŒčż™čĄ¨ç¤şćˆ‘äťŹé€ščż‡ĺź•ç”¨čŽˇĺ– sum ĺ˜é‡ďźšĺœ¨ Lambda ĺ†…éƒ¨ďźŒsum ć˜Żä¸€ä¸Şĺź•ç”¨ďźŒć‰€äťĽĺŻšĺŽƒčż›čĄŒçš„äťťä˝•ć”šĺ˜éƒ˝äźšĺŻš Lambda ĺ¤–éƒ¨çš„ sum ĺ˜é‡é€ ćˆĺ˝ąĺ“。
ĺŚ‚ćžœä˝ ä¸ć˜Żéœ€čŚĺź•ç”¨ďźŒĺŞéœ€čŚĺ˜é‡çš„拡č´ďźŒĺŞéœ€čŚĺŽťćŽ‰ & 尹弽。
ĺŚ‚ćžœä˝ ćƒłčŽˇĺ–多个ĺ˜é‡ďźŒĺŞéœ€čŚç”¨é€—ĺˇčż›čĄŒĺˆ†éš”ďźŒĺ°ąĺƒĺ‡˝ć•°çš„ĺ‚ć•°é‚Łć ˇă€‚
盎ĺ‰čż˜ä¸čƒ˝ç›´ćŽĽčŽˇĺ–ćˆĺ‘˜ĺ˜é‡ďźŒä˝†ć˜Żä˝ ĺŻäťĽčŽˇĺ– thisďźŒç„śĺŽé€ščż‡ĺŽƒčŽżé—Žĺ˝“ĺ‰ĺŻščąĄçš„ć‰€ćœ‰ćˆĺ‘˜ă€‚
ĺœ¨čƒŒĺŽďźŒLambda 莡ĺ–çš„ĺ˜é‡äźšäżĺ˜ĺœ¨ä¸€ä¸Şéšč—的寚蹥ä¸ă€‚ä¸čż‡ďźŒĺŚ‚ćžœçź–čŻ‘ĺ™¨çĄŽčŽ¤ Lambda ä¸äźšĺœ¨ĺ˝“ĺ‰ĺą€éƒ¨ä˝œç”¨ĺŸŸäš‹ĺ¤–ä˝żç”¨ďźŒĺŽƒĺ°ąäźščż›čĄŒäź˜ĺŒ–ďźŒç›´ćŽĽä˝żç”¨ĺą€ĺŸŸĺ˜é‡ă€‚
ćœ‰ä¸€ä¸Şĺˇć‡’的办法ĺŻäťĽčގĺ–ć‰€ćœ‰ĺą€éƒ¨ĺ˜é‡ă€‚用 [&] ćĽčގĺ–ĺŽƒäťŹçš„ĺź•ç”¨ďź›ç”¨ [=] ćĽčގĺ–ĺŽƒäťŹçš„ć‹ˇč´ă€‚ä¸čż‡ćœ€ĺĽ˝ä¸čŚčż™ć ˇĺšďźŒĺ› 为埕用ĺ˜ć›´çš„ç”Ÿĺ‘˝ĺ‘¨ćœŸĺžˆĺŻčƒ˝çŸäşŽ Lambda çš„ç”Ÿĺ‘˝ĺ‘¨ćœŸďźŒčż™äźšĺŻźč‡´ĺĽ‡ć€Şçš„é”™čŻŻă€‚ĺ°ąçŽ—ä˝ čŽˇĺ–çš„ć˜Żä¸€ä¸Şĺ˜é‡çš„拡č´ďźŒä˝†ĺŽƒćœŹčşŤć˜Żä¸€ä¸ŞćŒ‡é’ˆďźŒäšŸäźšĺŻźč‡´ĺ´Šćşƒă€‚ĺŚ‚ćžœć˜ŽçĄŽçš„ĺˆ—ĺ‡şä˝ äžčľ–çš„ĺ˜é‡ďźŒäźšć›´ĺŽšć˜“éżĺź€čż™çąťé™ˇé˜ąă€‚ĺ…łäşŽčż™ä¸Şé™ˇé˜ąć›´ĺ¤šçš„äżĄćŻďźŒčŻˇçœ‹çœ‹Â â€œEffective Modern C++†的珏 31 ćĄă€‚
ĺŚ‚ćžœä˝ ĺœ¨ç”¨ć–°çš„čżžćŽĽéŁŽć źÂ (ä˝ ĺş”čŻĽç”¨ďźŒĺ› ä¸şćœ‰éžĺ¸¸ĺĽ˝çš„繝型厉全ďź)ďźŒĺ°ąĺŻäťĽĺœ¨ćŽĽć”śçŤŻä˝żç”¨ LambdaďźŒčż™ĺŻšäşŽčžƒĺ°çš„处ç†ĺ‡˝ć•°ćĽčŻ´çŽ€ç›´ĺ¤ŞćŁ’äş†ă€‚
下é˘ć˜Żä¸€ä¸Şç”ľčŻć‹Źĺˇĺ™¨çš„ç¤şäž‹ďźŒç”¨ćˆˇĺŻäťĽčž“ĺ…Ľć•°ĺ—焜ĺŽć‹¨ĺ‡şç”ľčŻďźš
Dialer::Dialer() {     mPhoneNumberLineEdit = new QLineEdit();     QPushButton* button = new QPushButton("Call");     /* ... */     connect(button, &QPushButton::clicked,             this, &Dialer::startCall); } void Dialer::startCall() {     mPhoneService->call(mPhoneNumberLineEdit->text()); }
ćˆ‘äťŹĺŻäťĽä˝żç”¨ Lambda 䝣替 startCall() 斚法
Dialer::Dialer() {     mPhoneNumberLineEdit = new QLineEdit();     QPushButton* button = new QPushButton("Call");     /* ... */     connect(button, &QPushButton::clicked, [this]() {         mPhoneService->call(mPhoneNumberLineEdit->text());     }); }
Lambda äšŸć˜ŻÂ QObject::sender() 的一个éžĺ¸¸ĺĽ˝çš„ć›żäťŁć–šćĄˆă€‚ćƒłĺƒä¸€ä¸‹ďźŒĺŚ‚ćžœćˆ‘äťŹçš„ć‹¨ĺˇĺ™¨çŽ°ĺœ¨ć˜Żä¸€çť„çš„ć•°ĺ—ćŒ‰é’Žçš„ć•°çť„ă€‚
沥使用 Labmda 的䝣ç ďźŒĺœ¨çť„ĺˆć•°ĺ—的旜候䟚ĺƒčż™ć ˇďźš
Dialer::Dialer() {     for (int digit = 0; digit setProperty("digit", digit);                 connect(button, &QPushButton::clicked,                 this, &Dialer::onClicked);     }     /* ... */ } void Dialer::onClicked() {     QPushButton* button = static_cast(sender());     int digit = button->property("digit").toInt();     mPhoneService->dial(digit); }
ćˆ‘äťŹĺŻäťĽä˝żç”¨Â QSignalMapper 嚜厝掉 Dialer::onClicked() ć–šćł•ďźŒä˝†ä˝żç”¨ Labmda äźšć›´çľć´ťć›´çŽ€ĺ•ă€‚ćˆ‘äťŹĺŞéœ€čŚčގĺ–ä¸ŽćŒ‰é’ŽĺŻšĺş”çš„ć•°ĺ—ďźŒç„śĺŽĺœ¨ Lambda ä¸ç›´ćŽĽĺ°ąčƒ˝č°ƒç”¨Â mPhoneService->dial()。
Dialer::Dialer() {     for (int digit = 0; digit dial(digit);             }         );     }     /* ... */ }
çœ‹čż™ćŽľäťŁç ďźš
void Worker::setMonitor(Monitor* monitor) {     connect(this, &Worker::progress,             monitor, &Monitor::setProgress); }
ĺœ¨čż™ä¸Şĺ°äž‹ĺä¸ďźŒćœ‰ä¸€ä¸Ş Worker 厞䞋ćĽĺ‘ Monitor ĺŽžäž‹ćŠĽĺ‘Ščż›ĺşŚă€‚ĺˆ°ç›Žĺ‰ä¸şć˘ďźŒčż˜ć˛Ąäť€äšˆé—Žé˘˜ă€‚
çŽ°ĺœ¨ĺ‡čŽžÂ Worker::progress() ćœ‰ä¸€ä¸Ş int 型的ĺ‚ć•°ďźŒĺšśä¸” monitor çš„ĺŚä¸€ä¸Şć–šćł•需čŚä˝żç”¨čż™ä¸Şĺ‚ć•°ĺ€źă€‚ćˆ‘äťŹäźšĺ°čŻ•čż™ć ˇĺšďźš
void Worker::setMonitor(Monitor* monitor) {     // Don't do this!     connect(this, &Worker::progress, [monitor](int value) {         if (value setProgress(value); } else {     monitor->markFinished(); }     }); }
çœ‹čľˇćĽć˛Ąé—Žé˘˜â€Śâ€Śä˝†ć˜Żčż™ćŽľäťŁç äźšĺŻźč‡´ĺ´Šćşƒďź
Qt çš„čżžćŽĽçłťçťŸĺžˆć™şčƒ˝ďźŒĺŚ‚ćžœĺ‘é€ć–šĺ’ŒćŽĽć”ść–šä¸çš„äťťä˝•ä¸€ä¸Şč˘Ťĺˆ é™¤ćŽ‰ďźŒĺŽƒĺ°ąäźšĺˆ é™¤čżžćŽĽă€‚ĺœ¨ćœ€ĺˆçš„ setMonitor() ä¸ďźŒĺŚ‚ćžœ monitor č˘Ťĺˆ é™¤äş†ďźŒčżžćŽĽäšŸäźšč˘Ťĺˆ é™¤ă€‚ä˝†çŽ°ĺœ¨ćˆ‘äťŹä˝żç”¨äş† Lambda ćĽä˝œä¸şćŽĽć”ść–šďźš Qt 盎ĺ‰ć˛Ąćœ‰ĺŠžćł•ĺ‘çŽ°ĺœ¨Â Lambda ä¸ä˝żç”¨äş† monitor。ĺłä˝ż monitor č˘Ťĺˆ é™¤ćŽ‰ďźŒLambda äťç„śäźšč°ƒç”¨ďźŒçť“ćžœĺş”ç”¨ĺ°ąäźšĺœ¨ĺ°čŻ•ĺź•ç”¨ monitor 的旜候ĺ‘ç”Ÿĺ´Šćşƒă€‚
为了éżĺ…ĺ´Šćşƒĺ‘ç”ŸďźŒä˝ čŚĺ‘ connect() č°ƒç”¨äź ĺ…Ľä¸€ä¸Şâ€œcontextâ€ĺ‚ć•°ďźŒĺƒčż™ć ˇďźš
void Worker::setMonitor(Monitor* monitor) {     // Do this instead!     connect(this, &Worker::progress, monitor,             [monitor](int value) { if (value setProgress(value); } else {     monitor->markFinished(); }     }); }
这掾䝣ç ä¸ďźŒćˆ‘䝏把 monitor ä˝œä¸şä¸Šä¸‹ć–‡äź ĺ…Ľäş† connect()。这ä¸äźšĺŻš Lambda çš„ć‰§čĄŒé€ ćˆĺ˝ąĺ“ďźŒä˝†ć˜Żĺœ¨ monitor č˘Ťĺˆ é™¤äš‹ĺŽďźŒQt 䟚注ć„ĺˆ°ĺšśč§Łé™¤Â Worker::progress() ĺ’Œ Lambda 䚋间的连掼。
čż™ä¸Şä¸Šä¸‹ć–‡čż˜äźšç”¨äşŽćŁ€ćľ‹čżžćŽĽć˜ŻĺŚĺœ¨é˜Ÿĺˆ—ä¸ă€‚ĺ°ąĺƒçťĺ…¸çš„ signal-slot čżžćŽĽé‚Łć ˇďźŒĺŚ‚ćžœä¸Šä¸‹ć–‡ĺŻščąĄä¸Žĺ‘射俥ĺˇçš„䝣ç ä¸ĺœ¨ĺŒä¸€ä¸Şçşżç¨‹ďźŒQt äźšĺ°†čżžćŽĽç˝Žĺ…Ľé˜Ÿĺˆ—ă€‚
ä˝ ĺŻčƒ˝ĺŻšä¸€ç§ĺź‚ćĽč°ƒç”¨ slot çš„ć–šćł•ćŻ”čžƒç†Ÿć‚‰ďźŒĺŽƒä˝żç”¨Â QMetaObject::invokeMethodă€‚ĺ…ˆĺŽšäš‰ä¸€ä¸Şçąťďźš
class Foo : public QObject { public slots:     void doSomething(int x); };
ä˝ ĺŻäťĽĺœ¨ Qt ä¸ä˝żç”¨ QMetaObject::invokeMethod ĺœ¨äş‹äťśĺžŞçŽŻčż”ĺ›žć—śč°ƒç”¨Â Foo::doSomething()ďźš
QMetaObject::invokeMethod(this, "doSomething",                           Qt::QueuedConnection, Q_ARG(int, 1));
这掾䝣ç äźšĺˇĽä˝œďźŒä˝†ć˜Żďźš
ĺŻäťĽé€ščż‡ĺœ¨Â QTimer::singleShot() ä¸č°ƒç”¨ Lambda ćĽäťŁć›żä¸Šé˘çš„䝣ç ďźš
QTimer::singleShot(0, [this]() {     doSomething(1); });
čż™ä¸Şć•ˆçŽ‡äźšç¨ä˝Žä¸€äş›ďźŒĺ› 为  QTimer::singleShot() äźšĺœ¨čƒŒĺŽĺˆ›ĺťşä¸€ä¸ŞĺŻščąĄďźŒä¸čż‡ďźŒĺŞčŚä˝ ä¸ć˜ŻčŚĺœ¨ä¸€ç§’ĺ†…č°ƒç”¨ĺžˆĺ¤šćŹĄďźŒčż™ç‚šć€§čƒ˝ćŸĺ¤ąĺŻäťĽĺż˝ç•Ľä¸čŽĄă€‚ć˜žç„śĺˆŠĺ¤§äşŽĺźŠă€‚
ä˝ ĺŒć ˇĺŻäťĽĺœ¨ Lambda ĺ‰é˘ćŒ‡ĺŽšä¸€ä¸Şä¸Šä¸‹ć–‡ďźŒčż™ĺœ¨ĺ¤šçşżç¨‹ä¸éžĺ¸¸ćœ‰ç”¨ă€‚但čŚĺ°ĺżƒďźšĺŚ‚ćžœä˝ ä˝żç”¨ä˝ŽäşŽ 5.6.0 ç‰ˆćœŹçš„ QtďźŒQTimer::singleShot() ćœ‰ä¸€ä¸Ş BUGÂ ĺœ¨ĺ¤šçşżç¨‹ä¸ä˝żç”¨ć—śäźšĺŻźč‡´ĺ´Šćşƒă€‚ćˆ‘äťŹć‰žĺˆ°äş†é‚Łä¸Şĺ›°éšžçš„ĺŠžćł•â€Śâ€Ś
ĺ¸Œćœ›ä˝ čƒ˝ĺ–œćŹ˘čż™çŻ‡ć–‡çŤ ďźŒĺšśĺ¸Œćœ›ä˝ çŽ°ĺœ¨ĺ°ąç”¨ćź‚äşŽçš„ Lambda čŻćł•替ć˘ćމĺ¤ćżçš„ć—§čŻćł•ďź
ĺŚ‚ä˝•ĺˆŠç”¨ C++ çš„ Lambda 襨螞ĺźćĺ‡ Qt 䝣ç ďźŒéŚ–ĺ‘äşŽć–‡çŤ - 䟯äšĺœ¨çşżă€‚