讓我們來談?wù)劦鞲对铮且粋€(gè)非常有用的工具敷钾,在整個(gè)EOS代碼庫(kù)中大量使用枝哄。如果您來自JavaScript背景,您可能已經(jīng)熟悉迭代器闰非,就像它們用于循環(huán)一樣膘格。迭代器的關(guān)鍵概念是提供一種更好的方法來遍歷項(xiàng)集合。額外的好處是您可以為任何自定義類實(shí)現(xiàn)迭代器接口财松,使迭代器成為遍歷數(shù)據(jù)的通用方法。
// @url: https://repl.it/@MrToph/CPPBasics-Iterators
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{2, 3, 5, 8};
// old way to iterate
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << "\n";
}
// using Iterators
// begin() returns an iterator that points to the beginning of the vector
// end() points to the end, can be compared using != operator
// iterators are incremented by using the + operator thanks to operator-overloading
for (vector<int>::iterator i = v.begin(); i != v.end(); i++)
{
// iterators are dereferenced by * like pointers
// returns the element the iterator is currently pointing to
cout << *i << "\n";
}
// auto keyword allows you to not write the type yourself
// instead C++ infers it from the return type of v.begin
for (auto i = v.begin(); i != v.end(); i++)
{
cout << *i << "\n";
}
// can use arithmetic to "jump" to certain elements
int thirdElement = *(v.begin() + 2);
cout << "Third: " << thirdElement << "\n";
// end is the iterator that points to the "past-the-end" element
// The past-the-end element is the theoretical element that would follow the last element in the vector.
// It does not point to any element, and thus shall not be dereferenced.
int lastElement = *(v.end() - 1);
cout << "Last: " << lastElement << "\n";
// do not go out of bounds by iterating past the end() iterator
// the behavior is undefined
// BAD: v.end() + 1, v.begin() + 10
}
在現(xiàn)代C++中纱控,迭代器是迭代元素集合(向量辆毡,列表,映射)的首選方式甜害。另外舶掖,auto關(guān)鍵字可以避免輸入word類型,但可能會(huì)導(dǎo)致代碼性能降低尔店。
Lambda表達(dá)式
使用迭代器眨攘,我們可以開始研究現(xiàn)代C++的函數(shù)式編程概念。標(biāo)準(zhǔn)庫(kù)中的許多函數(shù)采用由兩個(gè)迭代器(開始和結(jié)束)和匿名函數(shù)(lambda函數(shù))表示的一系列元素作為參數(shù)嚣州。然后將此匿名函數(shù)應(yīng)用于范圍內(nèi)的每個(gè)元素鲫售。它們被稱為匿名函數(shù),因?yàn)樗鼈儾皇墙壎ǖ阶兞扛秒龋撬鼈兪嵌踢壿媺K情竹,作為內(nèi)聯(lián)參數(shù)傳遞給更高階函數(shù)。通常匀哄,它們對(duì)于傳遞給它們的函數(shù)是唯一的秦效,因此不需要具有名稱(匿名)的整個(gè)開銷。
有了它涎嚼,我們可以實(shí)現(xiàn)類似于排序阱州,映射,過濾等的構(gòu)造法梯,這些構(gòu)造在JavaScript等語(yǔ)言中很容易實(shí)現(xiàn):
[1,2,3,4].map(x => x*x).filter(x => x % 2 === 1).sort((a,b) => b - a)
C++中的代碼并不簡(jiǎn)潔苔货,但結(jié)構(gòu)相同。來自std庫(kù)的許多函數(shù)式編程助手以半開間隔運(yùn)行,這意味著包括較低范圍蒲赂,排除較高范圍阱冶。
// @url: https://repl.it/@MrToph/CPPBasics-Lambdas
#include <iostream>
#include <vector>
// for sort, map, etc.
#include <algorithm>
using namespace std;
int main()
{
vector<int> v{2, 1, 4, 3, 6, 5};
// first two arguments are the range
// v.begin() is included up until v.end() (excluded)
// sorts ascending
sort(v.begin(), v.end());
// in C++, functions like sort mutate the container (in contrast to immutability and returning new arrays in other languages)
for (auto i = v.begin(); i != v.end(); i++)
{
cout << *i << "\n";
}
// sort it again in descending order
// third argument is a lambda function which is used as the comparison for the sort
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// functional for_each, can also use auto for type
for_each(v.begin(), v.end(), [](int a) { cout << a << "\n"; });
vector<string> names{"Alice", "Bob", "Eve"};
vector<string> greetings(names.size());
// transform is like a map in JavaScript
// it applies a function to each element of a container
// and writes the result to (possibly the same) container
// first two arguments are range to iterate over
// third argument is the beginning of where to write to
transform(names.begin(), names.end(), greetings.begin(), [](const string &name) {
return "Hello " + name + "\n";
});
// filter greetings by length of greeting
auto new_end = std::remove_if(greetings.begin(), greetings.end(), [](const string &g) {
return g.size() > 10;
});
// iterate up to the new filtered length
for_each(greetings.begin(), new_end, [](const string &g) { cout << g; });
// alternatively, really erase the filtered out elements from vector
// so greetings.end() is the same as new_end
// greetings.erase(new_end, greetings.end());
// let's find Bob
string search_name = "Bob";
// we can use the search_name variable defined outside of the lambda scope
// notice the [&] instead of [] which means that we want to do "variable capturing"
// i.e. make all local variables available to use in the lambda function
auto bob = find_if(names.begin(), names.end(), [&](const string &name) {
return name == search_name;
});
// find_if returns an iterator referncing the found object or the past-the-end iterator if nothing was found
if (bob != names.end())
cout << "Found name " << *bob << "\n";
}
匿名函數(shù)的語(yǔ)法是在C++中習(xí)慣的東西。它們由括號(hào)指定滥嘴,后跟參數(shù)列表木蹬,如[](int a,int b) - > bool {return a> b; }
若皱。請(qǐng)注意镊叁,- > bool
指定一個(gè)布爾返回值。通常走触,您可以避免表達(dá)返回類型晦譬,因?yàn)樗梢詮暮瘮?shù)體中的返回類型推斷出來。
如果要使用lambda函數(shù)之外的作用域中定義的變量互广,則需要進(jìn)行變量捕獲敛腌。還有可能通過引用或值將參數(shù)傳遞給您的函數(shù)。
- 要通過引用傳遞惫皱,您需要使用
&
字符啟動(dòng)lambda(就像在函數(shù)中使用引用時(shí)一樣):[&]
- 要傳遞值像樊,請(qǐng)使用
=
字符:[=]
還可以通過值和參考來混合和匹配捕獲。
例如旅敷,[=生棍,&foo]
將為除foo
之外的所有變量創(chuàng)建副本,這些變量通過引用捕獲媳谁。
它有助于理解使用lambdas時(shí)幕后發(fā)生的事情:
事實(shí)證明涂滴,lambdas的實(shí)現(xiàn)方式是創(chuàng)建一個(gè)小類;這個(gè)類重載了operator()
,因此它就像一個(gè)函數(shù)一樣晴音。lambda函數(shù)是這個(gè)類的一個(gè)實(shí)例;構(gòu)造類時(shí)柔纵,周圍環(huán)境中的任何變量都將傳遞給lambda函數(shù)類的構(gòu)造函數(shù)并保存為成員變量。事實(shí)上段多,這有點(diǎn)像已經(jīng)可能的仿函數(shù)的想法首量。C++ 11的好處是,這樣做變得非常簡(jiǎn)單——所以你可以一直使用它进苍,而不是僅僅在非常罕見的情況下編寫一個(gè)全新的類是有意義的加缘。
Lambda函數(shù)在EOS智能合約中大量使用,因?yàn)樗鼈兲峁┝艘环N非常方便的方法來修改少量代碼中的數(shù)據(jù)觉啊。標(biāo)準(zhǔn)庫(kù)中有更多函數(shù)拣宏,它們與我們?cè)?code>sort,transform
杠人,remove_if
和find_if
中看到的函數(shù)類似勋乾。它們都通過<algorithm>
標(biāo)頭導(dǎo)出宋下。
======================================================================
分享一些比特幣、以太坊辑莫、EOS等區(qū)塊鏈相關(guān)的交互式在線編程實(shí)戰(zhàn)教程:
- EOS入門教程学歧,本課程幫助你快速入門EOS區(qū)塊鏈去中心化應(yīng)用的開發(fā),內(nèi)容涵蓋EOS工具鏈各吨、賬戶與錢包枝笨、發(fā)行代幣、智能合約開發(fā)與部署揭蜒、使用代碼與智能合約交互等核心知識(shí)點(diǎn)横浑,最后綜合運(yùn)用各知識(shí)點(diǎn)完成一個(gè)便簽DApp的開發(fā)。
- 深入淺出玩轉(zhuǎn)EOS錢包開發(fā)屉更,本課程以手機(jī)EOS錢包的完整開發(fā)過程為主線徙融,深入學(xué)習(xí)EOS區(qū)塊鏈應(yīng)用開發(fā),課程內(nèi)容即涵蓋賬戶瑰谜、計(jì)算資源欺冀、智能合約、動(dòng)作與交易等EOS區(qū)塊鏈的核心概念萨脑,同時(shí)也講解如何使用eosjs和eosjs-ecc開發(fā)包訪問EOS區(qū)塊鏈脚猾,以及如何在React前端應(yīng)用中集成對(duì)EOS區(qū)塊鏈的支持。課程內(nèi)容深入淺出砚哗,非常適合前端工程師深入學(xué)習(xí)EOS區(qū)塊鏈應(yīng)用開發(fā)。
- java比特幣開發(fā)教程砰奕,本課程面向初學(xué)者蛛芥,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲(chǔ)军援、去中心化共識(shí)機(jī)制仅淑、密鑰與腳本、交易與UTXO等胸哥,同時(shí)也詳細(xì)講解如何在Java代碼中集成比特幣支持功能涯竟,例如創(chuàng)建地址、管理錢包空厌、構(gòu)造裸交易等庐船,是Java工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程。
- php比特幣開發(fā)教程嘲更,本課程面向初學(xué)者筐钟,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲(chǔ)赋朦、去中心化共識(shí)機(jī)制篓冲、密鑰與腳本李破、交易與UTXO等,同時(shí)也詳細(xì)講解如何在Php代碼中集成比特幣支持功能壹将,例如創(chuàng)建地址嗤攻、管理錢包、構(gòu)造裸交易等诽俯,是Php工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程妇菱。
- c#比特幣開發(fā)教程,本課程面向初學(xué)者惊畏,內(nèi)容即涵蓋比特幣的核心概念恶耽,例如區(qū)塊鏈存儲(chǔ)、去中心化共識(shí)機(jī)制颜启、密鑰與腳本偷俭、交易與UTXO等,同時(shí)也詳細(xì)講解如何在C#代碼中集成比特幣支持功能缰盏,例如創(chuàng)建地址涌萤、管理錢包、構(gòu)造裸交易等口猜,是C#工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程负溪。
- java以太坊開發(fā)教程,主要是針對(duì)java和android程序員進(jìn)行區(qū)塊鏈以太坊開發(fā)的web3j詳解济炎。
- python以太坊川抡,主要是針對(duì)python工程師使用web3.py進(jìn)行區(qū)塊鏈以太坊開發(fā)的詳解。
- php以太坊须尚,主要是介紹使用php進(jìn)行智能合約開發(fā)交互崖堤,進(jìn)行賬號(hào)創(chuàng)建、交易耐床、轉(zhuǎn)賬密幔、代幣開發(fā)以及過濾器和交易等內(nèi)容。
- 以太坊入門教程撩轰,主要介紹智能合約與dapp應(yīng)用開發(fā)胯甩,適合入門。
- 以太坊開發(fā)進(jìn)階教程堪嫂,主要是介紹使用node.js偎箫、mongodb、區(qū)塊鏈溉苛、ipfs實(shí)現(xiàn)去中心化電商DApp實(shí)戰(zhàn)镜廉,適合進(jìn)階。
- ERC721以太坊通證實(shí)戰(zhàn)愚战,課程以一個(gè)數(shù)字藝術(shù)品創(chuàng)作與分享DApp的實(shí)戰(zhàn)開發(fā)為主線娇唯,深入講解以太坊非同質(zhì)化通證的概念齐遵、標(biāo)準(zhǔn)與開發(fā)方案。內(nèi)容包含ERC-721標(biāo)準(zhǔn)的自主實(shí)現(xiàn)塔插,講解OpenZeppelin合約代碼庫(kù)二次開發(fā)梗摇,實(shí)戰(zhàn)項(xiàng)目采用Truffle,IPFS想许,實(shí)現(xiàn)了通證以及去中心化的通證交易所伶授。
- C#以太坊,主要講解如何使用C#開發(fā)基于.Net的以太坊應(yīng)用流纹,包括賬戶管理糜烹、狀態(tài)與交易、智能合約開發(fā)與交互漱凝、過濾器和交易等疮蹦。
- Hyperledger Fabric 區(qū)塊鏈開發(fā)詳解,本課程面向初學(xué)者茸炒,內(nèi)容即包含Hyperledger Fabric的身份證書與MSP服務(wù)愕乎、權(quán)限策略、通道配置與啟動(dòng)壁公、鏈碼通信接口等核心概念感论,也包含F(xiàn)abric網(wǎng)絡(luò)設(shè)計(jì)、nodejs鏈碼與應(yīng)用開發(fā)的操作實(shí)踐紊册,是Nodejs工程師學(xué)習(xí)Fabric區(qū)塊鏈開發(fā)的最佳選擇比肄。
- Hyperledger Fabric java 區(qū)塊鏈開發(fā)詳解,課程面向初學(xué)者囊陡,內(nèi)容即包含Hyperledger Fabric的身份證書與MSP服務(wù)薪前、權(quán)限策略、頻道配置與啟動(dòng)关斜、鏈碼通信接口等核心概念,也包含F(xiàn)abric網(wǎng)絡(luò)設(shè)計(jì)铺浇、java鏈碼與應(yīng)用開發(fā)的操作實(shí)踐痢畜,是java工程師學(xué)習(xí)Fabric區(qū)塊鏈開發(fā)的最佳選擇。
- tendermint區(qū)塊鏈開發(fā)詳解鳍侣,本課程適合希望使用tendermint進(jìn)行區(qū)塊鏈開發(fā)的工程師丁稀,課程內(nèi)容即包括tendermint應(yīng)用開發(fā)模型中的核心概念,例如ABCI接口倚聚、默克爾樹线衫、多版本狀態(tài)庫(kù)等,也包括代幣發(fā)行等豐富的實(shí)操代碼惑折,是go語(yǔ)言工程師快速入門區(qū)塊鏈開發(fā)的最佳選擇授账。
匯智網(wǎng)原創(chuàng)翻譯枯跑,轉(zhuǎn)載請(qǐng)標(biāo)明出處。這里是C++開發(fā)EOS基礎(chǔ)指南:迭代器和Lambda表達(dá)式