1. 程式人生 > >C++ lambda表示式的編譯器實現..

C++ lambda表示式的編譯器實現..



現在,Android已經全面轉向C++11/14標準了,看程式碼的話,很多地方變化很大,新標準真的是有點顛覆性的,感覺已經不會C++了。今天有看到lambda表示式,突然想看一下,這貨是怎麼實現的,如下,寫了個例子,分別呼叫3個lambda表示式:

#include <stdlib.h>
#include <stdio.h>

//1. 無引數
auto hello = [] () {printf( "Hello world!\n");};
	
// 2. 一個引數
auto hello_int = [] (int val){ printf("the value is %d\n", val); }; 
	
int main(int argc, char **argv) {

	hello();
	hello_int(argc);

    // 3. 帶捕獲列表的lambda表示式
	auto lambda = [argc, argv]() {printf("param: %d, path is:%s\n", argc, argv[0]);};
	lambda();
	return 0;	
}
很簡單定義三個lambda表示式,lambda表示式就不細說是什麼了,基本上是介紹新標準的書,都會說的很明白。這裡想看一下,具體編譯器是怎麼實現表示式的呢?第一印象,應該是表示式按照行內函數的方式實現的吧,呼叫的地方自動展開,這樣引數、捕獲列表啥的都很好實現。 簡單看一下,編譯時不優化,反彙編看一下,如下,呼叫的main函式:

上面按順序呼叫的,就是程式碼中對應的三個lambda表示式。從這個反彙編看,貌似和猜想的不一樣是調了函式不是內聯展開。
紅色框住的呼叫函式[藍色是實際的符號,灰色是demangle後的,分析看這個],分別是:

$_0::operator()(void)       
$_1::operator()(int)     
main::$_2::operator() const(void)
這是三個過載的()操作符.. 呼叫前看到有壓入this引數,這是物件的方法呼叫,從反彙編看,是棧上建立物件,然後直接使用,使用是通過operator().. 這貨不就是函式物件麼???? OK,那就明白了,lambda表示式,編譯器自動轉換成函式物件執行。。。。 上面的例子,編譯器轉換的如下:
#include <stdlib.h>
#include <stdio.h>

class $_0 {
public:
	void operator() {
	    printf( "Hello world!\n");  	
	}	
};

class $_1 {
public:
	void operator(int va) {
	     printf("the value is %d\n", val);
	}	
};


class main::$_2 {
public:
	main::$_2(int i, char **v): argc(i), argv(v) {}
	//帶捕獲列表的,不能修改捕獲列表...
	void operator() const {
	    printf("param: %d, path is:%s\n", argc, argv[0]);
	}
	
private:
	int argc;
	char **argv;
}
	
int main(int argc, char **argv) {

	$_0 hello;
	hello();
	
	$_1 hello_int;
	hello_int(argc);

	main::$_2 lambda(argc, argv);
	lambda();
	
	return 0;
}
這裡,lambda轉換後的符號,是編譯器自動生成的,看起來稍有點彆扭。

相關推薦

C++ lambda表示式編譯器實現..

 現在,Android已經全面轉向C++11/14標準了,看程式碼的話,很多地方變化很大,新標準真的是有點顛覆性的,感覺已經不會C++了。今天有看到lambda表示式,突然想看一下,這貨是怎麼實現的,如下,寫了個例子,分別呼叫3個lambda表示式: #include

C++ lambda表示式總結

    一個lambda表示式用於建立閉包。lambda表示式與任何函式類似,具有返回型別、引數列表和函式體。與函式不同的是,lambda能定義在函式內部。lambda表示式具有如下形式 [ capture list ] ( parameter list) -> r

在EF中使用Expression自動生成p=>new Entity(){X="",Y="",..}格式的Lambda表示式靈活實現按需更新

一、基本介紹                                        

使用ES6新陣列方法(象C# Lambda表示式一樣寫查詢語句)

let people = [ {id: 1, name: "a", age: 12}, {id: 2, name: "b", age: 13}, {id: 3, name: "c", age: 14}, {id: 4, name: "d", age: 15}

C++ lambda表示式

1. lambda表示概念 可將lambda表示式視為包含公有operator()的匿名結構(或類),從這種意義上說,lambda表示式屬於函式物件。從上面所講到的進行分析: for_each(vectorElement.begin(), vectorElement.en

Collections.sort()方法和lambda表示式結合實現集合的排序

1.使用Collections.sort()實現集合的排序,這裡的方法具體指的是:   Collections.sort(List list, Compatator c)       第一個引數:為要進行排序的集合。     第二個引數:Compatator的實現,指定排序的方式。   2

c++ lambda表示式常用的情形

lambda表示式介紹 懶,摘自msdn Capture 子句(在 C++ 規範中也稱為 lambda 引導。) 引數列表(可選)。 (也稱為 lambda 宣告符) 可變規範(可選)。 異常規

C++ lambda表示式入門

1.lambda表示式 lambda表示式 是一個函式,一個匿名函式,也就是沒有函式名的函式,為什麼不需要函式名呢,因為我們直接(一次性的)用它,嵌入式用的它,不需要其他地方用它。 也叫閉包,閉就是封閉的意思,就是其他地方都不用他,包就是函式。 lambda表示

C++ lambda表示式一個非常簡單的例子

如果我想要定義一個指向int為返回值,兩個int為引數的函式的指標,有兩種方法1: 先宣告一個函式int func(int, int);然後使用decltype推斷這個func的型別作為新定義的型別的型別typedef decltype(func) * Func1;2: 直接

C#Lambda表示式

需求 有時候我們需要傳遞一個很方法的引用,我們很確定這個方法僅僅會呼叫這一次,單獨為它建立一個方法感覺有些浪費,但是又必須用到這個方法。又或者臨時需要一個方法,但是思考半天想不出該給這個方法取什麼名字(有過這個經歷的同學握個爪)。這個時候Lambda就派上用場

C# Lambda表示式詳細總結

(一)輸入引數 在Lambda表示式中,輸入引數是Lambda運算子的左邊部分。它包含引數的數量可以為0、1或者多個。只有當輸入引數為1時,Lambda表示式左邊的一對小括弧才可以省略。輸入引數的數量大於或者等於2時,Lambda表示式左邊的一對小括弧中的多個引

C# => Lambda表示式理解

本文參考網上的部落格和找到的資料加上個人理解編寫的,主要的程式碼借鑑:http://www.cnblogs.com/knowledgesea/p/3163725.html、百度百科 希望能夠幫助理解l

C# Lambda表示式詳細

(一)輸入引數 在Lambda表示式中,輸入引數是Lambda運算子的左邊部分。它包含引數的數量可以為0、1或者多個。只有當輸入引數為1時,Lambda表示式左邊的一對小括弧才可以省略。輸入引數的數量大於或者等於2時,Lambda表示式左邊的一對小括弧中的多個引

學習C++——lambda表示式

上面三個是C++學習網站,有助於瞭解C++11的新特性。 lambda表示式(C++11) 1、介紹lambda 我們使用過的僅有兩種可呼叫物件是函式和函式指標。還有其他兩種可呼叫物件:過載了函式呼叫運算子的類,以及lambda表示式。 一個lambda表示式表示一個

C++ lambda 表示式傳遞的變數預設不可變

我遇到如下問題: int count=0; listener->onTouchMoved=[count](Touch* t,Event* e){ count++; log("onTouchMoved");

C# Lambda表示式

上一節中,我們講到:在 2.0 之前的 C# 版本中,宣告委託的唯一方法是使用命名方法。  C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表示式取代了匿名方法,作為編寫內聯程式碼的首選方式。  有一種情況下,匿名方法提供了 Lambda 表示式

c++ lambda表示式(匿名函式)的使用總結

#include <iostream> using namespace std; //[=] () mutable throw() -> int {} /** * lambda expression * “Lambda 表示式”(lambda exp

C#lambda表示式和匿名函式

lambda表示式也被稱為匿名函式,何為匿名函式? 匿名沒有真實名字,當然在C#中就是沒有函式名了,C#裡有兩種匿名函式的寫法,一種是早期推出的匿名函式,而另一種就是拉姆達(lambda)表示式了,那麼這兩種有什麼不同,分別怎麼用的,下面介紹一下. 我個人覺得吧,在寫程式碼

LINQ 通過動態生成lambda表示式實現根據指定屬性名稱對序列進行排序

目前,對於Linq只是初步接觸,還不熟悉,做專案的時候想到一個問題,如果想要查詢任意欄位的排序結果集,該怎麼實現? 我們知道,T-SQL是非常容易解決這個問題,只要簡單通過拼接T-SQL就可以達到該效果。 那麼,Linq該怎麼實現呢? 網上查了很多資料,找到一種辦法就是通過

c++ lambda表示式捕獲變數引數

[]不捕獲任何變數 [&]捕獲外部作用域中所有變數,並作為引用在函式體重使用 [=]捕獲外部作用域中所有變數,並作為副本在函式體重使用 [=,&foo]捕獲外部作用域中所有變數,並作為副本在函式體重使用,對於foo按引用捕獲 [foo]當作副本捕獲foo,不