C++ lambda

來源:互聯網
上載者:User

標籤:文法   cto   https   接受   資料   問題:   named   printf   檢查   

最簡單的lambda:

int main(){    auto lambda = []{};    lambda();}

讓lambda更有用,就要捕捉局部變數。

#include <stdio.h>int main(){    int x = 1;        auto lambda = [x] {         printf("x=%d",x);     };     lambda();}

[x]是按值方式的捕捉,而且lambda對應的那個可調用的方法,是const。可以腦補這個等價物:

#include <stdio.h>int main(){    int x=1;        class unnamed_functor{    public:        unnamed_functor(int arg): x{arg}{}        void operator()() const{
// x=2; 錯誤,const函數內不能修改成員變數 printf("x=%d",x); } int x; }; unnamed_functor lambda{x}; lambda();}

可以使用mutable重新標記lambda函數,這個標記會清除const標記。例如:

#include <stdio.h>int main(){    int x = 1;        auto lambda = [x] mutable{         x=2;        printf("in lambda x=%d\n",x);     };     lambda();    printf("x=%d\n",x); }

[&y]是按照引用方式捕捉局部變數。例如:

#include <stdio.h>int main(){    int x=1, y= 2;        auto lambda = [x, &y] {         y=3;        printf("in lambda y=%d\n",y);     };     lambda();    printf("y=%d\n",y); }

可見,按照引用方式捕捉的局部變數,不用標記mutable也能更改y值。腦補如下虛擬碼:

#include <stdio.h>int main(){    int x=1,y=2 ;        class unnamed_functor{    public:        unnamed_functor(int x_, int& y_): x{x_},y(y_){}        void operator()() const{            // x=2; 錯誤,const函數內不能修改成員變數            y=3;            printf("in lambda y=%d\n",y);          }        int x;        int& y;    };         unnamed_functor lambda(x,y);    lambda();    printf("y=%d\n",y); }

這裡有個驚人的知識盲點,const成員函數能修改引用資料成員。仔細分析一下,const成員函數,關鍵意圖是不更改對象的狀態。對於int& y資料成員,就是不能更改此引用指向的對象。
當檢查y=3時,並沒有改變y所指向的對象(引用的本質是指標或者對象地址),因此與const不矛盾。這就解釋了lambda不用加mutable就能搞定引用捕捉的局部變數的修改問題。

lambda作為一個Callable,可以接受任意調用參數:

int main(){    int x=1;    auto lambda = [x](int arg){ return x+arg; }    std::cout << lambda(2); // show 3}

C++14開始,lambda能有自己的內部狀態變數了。從前只有兩個狀態來源:[]捕捉的局部變數( automatic storage duaration 不能是全域變數)()捕捉的調用參數。
例如:

#include <stdio.h>auto generator = [x = 0] () mutable {  return x++;};int main(){    auto a = generator(); // == 0    auto b = generator(); // == 1    auto c = generator(); // == 2}

腦補一下這個東西的等價物:

#include <stdio.h>class generator{public:    generator():x(0){}    int operator()(){        return x++;    }    int x;};int main(){    auto a = generator(); // == 0    auto b = generator(); // == 1    auto c = generator(); // == 2}

lambda捕捉能力進一步增強,可以捕捉任意的運算式。考慮如下問題:

#include <stdio.h>#include <memory>int main(){    auto p = std::make_unique<int>(1);    //auto q = p; error:不能copy    //auto k = std::move(p); ok: 能move copy        auto lambda = [p] {         //...    };}

顯然,傳值方式失敗了,因為unique_ptr不支援copy。為此,使用C++14的新文法:

#include <stdio.h>#include <memory>int main(){    auto p = std::make_unique<int>(1);    //auto q = p; error:不能copy    //auto k = std::move(p); ok: 能move copy    auto lambda = [k=std::move(p)] {         //...    };}

lambda捕捉this指標的文法:

#include <stdio.h>#include <memory>struct MyObj {      int value{ 123 };    MyObj() = default;    MyObj(const MyObj& other){        value = other.value;        printf("MyObj(const MyObj& other) \n");    }        auto getValueCopy() {      return [*this] { return value; };    }    auto getValueRef() {       return [this] { value=111; return value; };    }};int main(){    MyObj mo;    auto valueCopy = mo.getValueCopy();    auto valueRef = mo.getValueRef();    mo.value = 321;    valueCopy(); // 123    valueRef(); // 321        printf("%d\n", mo.value);    }

參考:https://github.com/AnthonyCalandra/modern-cpp-features#lambda-capture-this-by-value

C++ lambda

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.