日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++教程之lambda表达式一

發布時間:2024/1/17 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++教程之lambda表达式一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是Lambda?

C++ 11加入了一個非常重要的特性——Lambda表達式。營里(戴維營)的兄弟都對Objective-C很熟悉,許多人多block情有獨鐘,將各種回調函數、代理通通都用它來實現。甚至有人選擇用FBKVOController、BlocksKit等開源框架將KVO、控件事件處理都改為通過block解決。原因就是簡單、方便、直觀,函數的定義和使用出現在同一個地方。這里的Lambda表達式實際上和block非常類似,當然如果你用它和Swift語言的閉包比較,那就是一回事了。下面先看幾個Lambda和block的示例代碼。

1 .Objective-C的block示例代碼,使用^表示block類型,總體來說與函數指針的定義類似。

#import <Foundation/Foundation.h>int main() { void (^block)() = ^void() { NSLog(@"In block"); }; block(); return 0; }

編譯運行:

$ clang main.m -framework Foundation $ ./a.out 2015-01-28 14:17:52.763 a.out[9901:165707] In block

2 .Swift的閉包,參數列表、返回值類型等都寫在花括號{}內部。

let closure = {() -> Void in println("In swift") } closure()

編譯運行:

$ swiftc main.swift $ ./main In swift

測試Swift也可以直接使用Playground或REPL(Read-Eval-Print-Loop)環境。

3 .C++的Lambda表達式。

#include <iostream>int main() { auto lambda = []() -> void{ std::cout << "In lambda" << std::endl; }; lambda(); return 0; }

編譯運行,注意使用C++ 11的特性進行編譯:

$ clang++ main.cpp -std=c++11 $ ./a.out In lambda

Lambda、block實際上都是一個閉包(closure),它們都類似于一個匿名的函數,但是擁有捕獲所在作用域中變量的能力;能夠將函數做為對象一樣使用。通常用它們來實現回調函數、代理等功能。

Lambda使用方法

1 .基本形式

語法序號
[ 捕獲列表 ] ( 形參數列表 ) mutable(可選) 異常屬性 -> 返回值類型 { 函數體 }(1)
[ capture-list ] ( params ) -> ret { body }(2)
[ capture-list ] ( params ) { body }(3)
[ capture-list ] { body }(4)
  • (1)為完整的形式,包含變量捕獲列表、形參列表、可變屬性(可選)和返回值類型等。
  • (2)省略了mutable,表示Lambda不能修改捕獲的變量。
  • Lambda的返回值類型如果可以由函數體中的實際返回值推導出,可以省略。
  • 如果沒有形參,可以省略圓括號。

2 .捕獲列表

lambda表達式中可以獲取(捕獲)它所在作用域中的變量值,并且有兩種捕獲方式:引用和值。我們可以在捕獲列表中設置各變量的捕獲方式。如果沒有設置捕獲列表,lambda默認不能捕獲任何的變量,這點與block不同。

#include <iostream>int main() { int a = 123; auto lambda = []()->void{ std::cout << "In lambda: " << a << std::endl; }; lambda(); return 0; }

編譯運行:

$ clang++ main.cpp -std=c++11 main.cpp:8:33: error: variable 'a' cannot be implicitly captured in a lambdawith no capture-default specifiedstd::cout << "In lambda: " << a << std::endl; ^ main.cpp:5:6: note: 'a' declared here int a = 123; ^ main.cpp:7:16: note: lambda expression begins here auto lambda = []()->void{ ^ 1 error generated.

在[]中設置捕獲列表,就可以在lambda中使用變量a了,這里使用按值(=, by value)捕獲。

#include <iostream>int main() { int a = 123; auto lambda = [=]()->void{ std::cout << "In lambda: " << a << std::endl; }; lambda(); return 0; }

編譯運行:

$ clang++ main.cpp -std=c++11 $ ./a.out In lambda: 123

捕獲列表的設置方式:

|設置方式|結果| |-|-| |[]|不捕獲| |[=]|全部按值捕獲| |[&]|全部按引用捕獲| |[a, b]|按值捕獲變量a和b| |[&a, b]|按引用捕獲a,按值捕獲b| |[&, a]|按值捕獲a,其它變量全部按引用捕獲| |[=, &a]|按引用捕獲a,其它全部按值捕獲|

注意: 捕獲列表沒有先后順序;捕獲列表中的變量不能出現重復申明,比如[&, &a]在&中已經包含了&a的申明了,因此不能再出現&a。

具體的捕獲類型,可以通過打印變量地址進行查看。

  • 按值捕獲:
auto lambda = [=]()->void{ std::cout << "In lambda: " << &a << std::endl; };

運行結果為:

$ clang++ main.cpp -std=c++11 $ ./a.out 0x7fff555c69b8 In lambda: 0x7fff555c69b0
  • 按引用捕獲:
auto lambda = [&]()->void{ std::cout << "In lambda: " << &a << std::endl; };

運行結果為:

$ clang++ main.cpp -std=c++11 $ ./a.out 0x7fff58a9b9b8 In lambda: 0x7fff58a9b9b8

3 .可變類型(mutable)

按值傳遞到lambda中的變量,默認是不可變的(immutable),如果需要在lambda中進行修改的話,需要在形參列表后添加mutable關鍵字(按值傳遞無法改變lambda外變量的值)。

#include <iostream>int main() { int a = 123; std::cout << a << std::endl; auto lambda = [=]() mutable ->void{ a = 234; std::cout << "In lambda: " << a << std::endl; }; lambda(); std::cout << a << std::endl; return 0; }

編譯運行結果為:

$ clang++ main.cpp -std=c++11 lishan:c_study apple$ ./a.out 123 In lambda: 234 #可以修改 123 #注意這里的值,并沒有改變

如果沒有添加mutable,則編譯出錯:

$ clang++ main.cpp -std=c++11 main.cpp:9:5: error: cannot assign to a variable captured by copy in anon-mutable lambdaa = 234; ~ ^ 1 error generated.

4 .返回值類型。

lambda的返回值類型可以省略,編譯器會根據實際返回值的類型自動推導。

#include <iostream>int main() { int a = 123; std::cout << a << std::endl; auto lambda = [=]() mutable{ a = 234; std::cout << "In lambda: " << a << std::endl; return a; }; int b = lambda(); std::cout << b << std::endl; return 0; }

編譯運行:

$ clang++ main.cpp -std=c++11 $ ./a.out 123 In lambda: 234 234

參考資料

  • https://msdn.microsoft.com/en-us/library/dd293603.aspx
  • http://www.oracle.com/technetwork/articles/servers-storage-dev/howto-use-lambda-exp-cpp11-2189895.html
  • http://en.cppreference.com/w/cpp/language/lambda
  • http://www.cprogramming.com/c++11/c++11-lambda-closures.html
  • 本文檔由長沙戴維營教育整理。

    轉載于:https://www.cnblogs.com/diveinedu/p/4335430.html

    總結

    以上是生活随笔為你收集整理的C++教程之lambda表达式一的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。