亚洲国产成人精品久久_欧美日韩国产综合一区二区_亚洲精品理论电影_色综合久久中文字幕

首頁 » 早鳥快報 » 咨詢 » 正文

貫穿C++11與C++17的Lambda到底是個什么?

放大字體  縮小字體 發(fā)布日期:2019-12-01  來源:來自互聯(lián)網(wǎng)  作者:來自互聯(lián)網(wǎng)  瀏覽次數(shù):646
導(dǎo)讀

在這篇文章里,我不僅要向你展示C++中的Lambda函數(shù),同時還要介紹它的內(nèi)部工作機制,以及Lambda函數(shù)的其他方方面面。 C++包含許多有用的通用函數(shù),如std::for

本文將詳解Lambda函數(shù)從定義到學(xué)習(xí)和使用,涉及一些不為人知的事情,如LIFE-立即調(diào)用的函數(shù)表達式,Lambda的類型。相信你已經(jīng)起了興趣,那就開始閱讀吧。

作者 | Vishal Chovatiya

譯者 | 蘇本如,責(zé)編 | maozz

以下為譯文:

Lambda函數(shù)是C++ 11中引入的現(xiàn)代C++的一個直觀概念,因此在互聯(lián)網(wǎng)上可以找到大量的關(guān)于Lambda函數(shù)的文章。但是仍然有一些不為人知的事情(如LIFE-立即調(diào)用的函數(shù)表達式,Lambda的類型等等)鮮有人談?wù)?。因此,在這篇文章里,我不僅要向你展示C++中的Lambda函數(shù),同時還要介紹它的內(nèi)部工作機制,以及Lambda函數(shù)的其他方方面面。

這篇文章的標(biāo)題有點誤導(dǎo)人。因為Lambda并不總是轉(zhuǎn)化為函數(shù)指針。實際上它是一個表達式(確切地說是唯一的閉包)。為了簡單起見,在這篇文章中,我會一直互換使用Lambda函數(shù)和Lambda表達式。

什么是Lambda函數(shù)?

Lambda函數(shù)是簡短的代碼片段,它:

不值得命名(匿名的、未被命名的、一次性的,等等,無論你怎么稱呼它),

也不能重復(fù)使用。

換句話說,它只是一種糖衣語法(syntactic sugar)。Lambda函數(shù)的語法定義如下:

[ capture list] (parameters) -> return-type

{ method definition

}

編譯器通常會計算Lambda函數(shù)本身的返回類型。因此,我們不需要顯式地給它指定一個尾置返回類型,如-> return-type。

但在一些復(fù)雜的情況下,編譯器無法推斷返回類型,這時候我們就需要給它指定一個返回類型。

為什么我們要使用Lambda函數(shù)?

C++包含許多有用的通用函數(shù),如std::for_each,它們可以很方便。不幸的是,它們的使用有時也很麻煩,特別是如果你想應(yīng)用的函子是特定函數(shù)的唯一函子的話。以下面的代碼為例:

structprint

{

voidoperator(intelement)

{

cout<< element << endl;

}

};

int main(void)

{

std::vector<int> v = {1, 2, 3, 4, 5};

std::for_each(v.begin, v.end, print);

return0;

}

如果你只是在特定的地方使用一次print,那么僅僅為了做一些瑣碎的和一次性的事情而編寫一個完整的類,就顯得有些過猶不及了。

對于上面的這種情形,使用內(nèi)聯(lián)代碼會更合適,這可以通過Lambda函數(shù)來實現(xiàn),如下所示:

std:for_each(v.begin, v.end, [](intelement) { cout<< element << endl; });

Lambda函數(shù)內(nèi)部是如何工作的?

[&i] ( ) { std::cout<< i; }

// is equivalent to

structanonymous

{

int&m_i;

anonymous(int&i) : m_i(i) {}

inlineautooperatorconst

{

std::cout<< i;

}

};

編譯器為每個Lambda函數(shù)生成如上所述的唯一閉包。注意,這是Lambda函數(shù)的核心所在。

捕獲列表將成為閉包中的構(gòu)造函數(shù)的參數(shù),如果將參數(shù)按值捕獲,那么相應(yīng)類型的數(shù)據(jù)成員將在閉包中創(chuàng)建。

此外,可以在Lambda函數(shù)的參數(shù)中聲明變量/對象,它們將成為調(diào)用operator函數(shù)的參數(shù)。

使用Lambda函數(shù)的好處

零成本抽象。對!你沒有看錯。Lambda函數(shù)不會降低性能,它的性能和普通的函數(shù)一樣好。

此外,Lambda函數(shù)使代碼變得更加緊湊、更加結(jié)構(gòu)化和更富有表現(xiàn)力。

學(xué)習(xí)Lambda表達式

按引用/值來捕獲,代碼如下:

int main

{

intx = 100, y = 200;

autoprint = [&] { // Capturing object by reference

std::cout<< __PRETTY_FUNCTION__ << " : "<< x << " , "<< y << std::endl;

};

print;

return0;

}

上面代碼的輸出如下:

main::<Lambda> : 100, 200

在上面的例子中,我在捕獲列表中對“&”符號作了注釋。它表示按引用來捕獲變量x和y。類似地,“=”符號表示按值捕獲,它將在閉包中創(chuàng)建相同類型的數(shù)據(jù)成員,并且將執(zhí)行copy-assignment操作。

請注意,參數(shù)列表是可選的,如果你不向Lambda表達式傳遞任何參數(shù),則可以省略空括號。

Lambda函數(shù)的捕獲列表

下表顯示了捕獲列表中不同用法的含義:

將Lambda函數(shù)作為參數(shù)傳遞,代碼如下:

template<typenameFunctor>

void f(Functor functor)

{

std::cout<< __PRETTY_FUNCTION__ << std::endl;

}

intg{ staticinti = 0; returni++; }

int main

{

autoLambda_func = [i = 0] mutable{ returni++; };

f(Lambda_func); // Pass Lambda

f(g); // Pass function

}

上面代碼的輸出如下:

FunctionType: voidf(Functor) [withFunctor = main::<Lambda(int)>]

FunctionType: voidf(Functor) [withFunctor = int(*)(int)]

你還可以將Lambda函數(shù)作為參數(shù)傳遞給其他函數(shù),就像我在上面編寫的普通函數(shù)一樣。

如果你注意到了,這里我在捕獲列表中聲明了變量i,它將成為數(shù)據(jù)成員。因此,每次調(diào)用Lambda_func時,它都將返回并遞增。

捕獲Lambda函數(shù)中的成員變量或this指針,代碼如下:

classExample

{

public:

Example : m_var(10) {}

voidfunc

{

[=] { std::cout<< m_var << std::endl; }; // IIFE

}

private:

intm_var;

};

int main

{

Example e;

e.func;

}

也可以使用[this], [=] 或者 [&]來捕獲This指針。在任何這些情況下,類中的數(shù)據(jù)成員(包括private類型的數(shù)據(jù)成員)都可以像在普通方法中那樣被訪問。

如果你看到Lambda表達式行,我在Lambda函數(shù)聲明的末尾使用了額外的 ,這個額外的 用來表示在聲明之后立即調(diào)用它,它被稱為IIFE(立即調(diào)用的函數(shù)表達式)。

C++的Lambda函數(shù)類型

泛型Lambda,代碼如下:

constautol = [](autoa, autob, autoc) {};

// is equivalent to

structanonymous

{

template<classT0, classT1, classT2>

autooperator(T0a, T1b, T2c) const

{

}

};

在C++ 14中引入的泛型Lambda,它可以使用auto標(biāo)識符捕獲參數(shù)。

可變泛型Lambda,代碼如下:

voidprint{}

template<typenameFirst, typename... Rest>

void print(const First &first, Rest &&... args)

{

std::cout<< first << std::endl;

print(args...);

}

int main

{

autovariadic_generic_Lambda = [](auto... param) {

print(param...);

};

variadic_generic_Lambda(1, "lol", 1.1);

}

帶可變參數(shù)包的Lambda在許多情況下都很有用,如代碼調(diào)試、不同數(shù)據(jù)輸入的重復(fù)操作等。

可變(Mutable)Lambda函數(shù)

通常,Lambda函數(shù)的call-operator(調(diào)用運算符)隱式為const-by-value(常量,按值捕獲),這意味著它是不可變的。如果要按值捕獲任何內(nèi)容,需要在Lambda函數(shù)體前使用mutable關(guān)鍵字。代碼如下所示:

[] mutable{}

// is equivalent to

structanonymous

{

autooperator// call operator

{

}

};

我們已經(jīng)在上面看到了上述情況的一個例子。希望你注意到了。

Lambda作為函數(shù)指針,代碼如下:

#include<iostream>

#include<type_traits>

int main

{

autofuncPtr = +[] {};

static_assert(std::is_same<decltype(funcPtr), void(*)>::value);

}

你可以強制編譯器生成Lambda作為函數(shù)指針,而不是像上面那樣在它前面添加+來使之成為閉包。

高階函數(shù):Lambda可以作為參數(shù)和返回值,代碼如下:

constautoless_than = [](autox) {

return[x](autoy) {

returny < x;

};

};

int main(void)

{

autoless_than_five = less_than(5);

std::cout<< less_than_five(3) << std::endl;

std::cout<< less_than_five(10) << std::endl;

return0;

}

再進一步,Lambda函數(shù)還可以返回另一個Lambda函數(shù)。這將為代碼的定制、代碼表示性和緊湊性(順便說一句,沒有這樣的詞)打開無限可能的大門。

constexpr Lambda表達式

從C++ 17開始,Lambda表達式可以被聲明為constexpr(常量表達式)。

constexprautosum = [](constauto&a, constauto&b) { returna + b; };

constexprintanswer = sum(10, 10);

即使你沒有指定constexpr關(guān)鍵字,如果函數(shù)調(diào)用運算符恰好滿足所有constexpr函數(shù)的要求,那么它也將是constexpr。

結(jié)束語

希望你喜歡這篇文章。我試著用幾個簡單的小例子來涵蓋使用Lambda的大多數(shù)復(fù)雜情況??紤]到代碼的表達性和易維護性,你應(yīng)該在滿足Lambda使用條件的所有地方都優(yōu)先使用它,就像你可以將其和大多數(shù)STL算法一起用于智能指針的自定義刪除器中一樣。

原文:https://hackernoon/all-about-Lambda-functions-in-cfrom-c11-to-c17-2t1j32qw

本文為 CSDN 翻譯,轉(zhuǎn)載請注明來源出處。

點擊閱讀原文參與開發(fā)者大調(diào)查,好禮送不停!

 
 
免責(zé)聲明
本文為會員免費發(fā)布,僅代表發(fā)布者個人觀點,本站未對其內(nèi)容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,作者需自行承擔(dān)相應(yīng)責(zé)任。涉及到版權(quán)或其他問題,請及時聯(lián)系我們刪除處理。
 
 
主站蜘蛛池模板: 天天人人精品| 亚洲午夜久久久影院伊人| 国产成人成网站在线播放青青| 亚洲精品乱码视频| 国产精品视频999| 99在线热播| 亚洲高清不卡一区| 亚洲精品一区二区毛豆| 日本免费高清一区二区| 97久久久免费福利网址| 粉嫩av免费一区二区三区| 国产精品精品一区二区三区午夜版| 深夜福利一区二区| 日韩欧美国产免费| 欧美综合激情网| 日本精品久久久久久久久久| 日本久久久精品视频| 奇米影视亚洲狠狠色| 久久成年人免费电影| 日韩av一区二区三区在线| 久久久欧美一区二区| 狠狠精品干练久久久无码中文字幕| 久久婷婷国产精品| 久久免费视频观看| 亚洲国产精品影视| 久久久久久久久久婷婷| 国产精品女视频| 热久久视久久精品18亚洲精品| 久久久久免费精品| 日韩精品欧美在线| 91精品视频免费看| 国产色综合天天综合网| www.xxxx精品| 久久久久久久97| 国产精品美女诱惑| 久久久久久伊人| 欧美成人在线影院| 久久亚洲精品国产亚洲老地址| 亚洲在线观看视频网站| 国产免费一区视频观看免费| 国产精品久久久久7777|