Modern C++ - Lambda

291天前 · 程式設計 · c++ · 628次阅读

Modern C++ - Lambda

lambda是一個閉合體,其本身是一種特殊的物件。
具有無名,變數捕獲等特徵的函式體。

爲什麼需要Lambda?

在以前,如果要傳遞函式作爲參數調用,你需要定義一個函式,並使用函式指標指向函式的位址。

類似:

auto exec(void(*func_ptr)(int), int x){
    return (*func_ptr)(x);
};
void func(int){}

void(*func_ptr)(int) = &func;

auto result = exec(func_ptr, 1);

這不夠優雅,也不方便。

而有了Lambda,你可以簡化程式碼:

auto exec(std::function<void(int)> func, int x){
    return func(x);
}
auto lambda_func = [](int){};

auto result = exec(lambda_func,1);

並且可以在調用者無需提供(額外)型參的情況下,捕獲變數以在內部使用:

int x;
auto func = [x](){
    return x*x;
};

auto i = func(); //調用者無需提供型參

否則,將要求永遠提供額外型參,這非常醜陋 (如果你使用過純C程式庫會理解)。

有了Lambda,無論靈活性或是簡化程式碼等方面都大大增加。

語法

lambda有幾種語法,基礎和最常見的語法是這樣:

  • [] () {}

    • [捕獲列表]
    • (型參列表)
    • {函式體}

還有:

  • [] {}

    • 省去型參列表(即不需要參數)
  • [] () -> returnType {}

    • -> 後置返回類型語法,在Lambda要指定返回類型,只能使用它
  • [] <> () {}

    • <模板> 就和函式模板一樣

等等。
當然,它還支援大多普通函式可使用的修飾符,諸如:
const , constexpr , static , noexcept....
同樣都需要後置聲明(在型參列表後)

捕獲列表

在[捕獲列表]中,你可以獨立捕獲或者指定捕獲模式:

捕獲模式:

  • [ = ]

    • 拷貝捕獲,當前上下文中的對象將拷貝一份到Lambda中
    • 其將延長捕獲的變數生命週期至Lambda的生命週期
    裸指標仍需注意淺拷貝問題
  • [ & ]
    • 引用捕獲,顧名思義,以引用模式捕獲上下文中的變數
    • 其不會改變變數的生命週期,並對源對象修改
    需要注意懸垂引用,特別是Lambda的生命週期長於捕獲的變數時

你也可以按變數捕獲(默認是拷貝,除非指定捕獲模式)

  • [var1 , var2, var3 ... 捕獲的變數] , 如果沒指定捕獲模式,則只會捕獲列表中的變數

指定特定變數的捕獲模式:

  • [=, &var1 , &var2] ,var1和var2將以引用模式捕獲,其他均以拷貝捕獲。

捕獲初始化

除了上述提到的,C++14起還支援捕獲初始化。

  • [ y = x + 1]
  • [ var = std::move(x) ]
  • [ ... arg = args] : 可變參數的初始化捕獲

以透過捕獲的變數來初始化Lambda體內的變數。
透過它,你還可以將某些變數的所有權轉移到Lambda中。

範例


// Event.hpp
#include <functional>
#include <string>

class Event {
    //...
    // 你可能想允許使用者傳入自己的日誌處理
    std::function<void(const std::string &)> logger;
    
    void func(const std::string & msg){
        if (logger){
            logger(msg);
        }
    }
    //...
};

// Main.cpp
#include <iostream>

int main(){
    Event event;

    //這裏將日誌輸出到標準輸出(終端)
    auto logger = [](const std::string & msg){
        std::cout << msg << std::endl;
        //也可以顯示到ui,日誌檔案,或任何回調
    }
    event.setLogger(logger);
}

很多標準庫,程式庫的容器都推薦使用Lambda,如 std:sort 和 std:condition_variable.wait等等。

使用Lambda來替代不必要的單獨函式是現代的推薦做法。

更詳盡內容參閱:

👍 0

cpp lambda

最后修改于94天前

评论

贴吧 狗头 原神 小黄脸
收起

贴吧

  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡

狗头

  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头

原神

  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神

小黄脸

  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  1. Anfsity 168天前

    c++ 的 lambda 看起来很丑但实际上功能非常强大,用了就回不去辣

    安详

目录

avatar

Hina

曇花一現

20

文章

96

评论

8

分类

初见

Oha Api隨機背景圖像Api-隨機音樂&在線免費聆聽jaychou音樂!

523天前

OwO

33

網站正在更新中...
站點正在更新功能與樣式,如有樣式錯誤,請嘗試刷新緩存