您好,登錄后才能下訂單哦!
讓我們來談談迭代器,它是一個非常有用的工具,在整個EOS代碼庫中大量使用。如果您來自JavaScript背景,您可能已經熟悉迭代器,就像它們用于循環一樣。迭代器的關鍵概念是提供一種更好的方法來遍歷項集合。額外的好處是您可以為任何自定義類實現迭代器接口,使迭代器成為遍歷數據的通用方法。
// @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
}
在現代C++中,迭代器是迭代元素集合(向量,列表,映射)的首選方式。另外,auto關鍵字可以避免輸入word類型,但可能會導致代碼性能降低。
使用迭代器,我們可以開始研究現代C++的函數式編程概念。標準庫中的許多函數采用由兩個迭代器(開始和結束)和匿名函數(lambda函數)表示的一系列元素作為參數。然后將此匿名函數應用于范圍內的每個元素。它們被稱為匿名函數,因為它們不是綁定到變量,而是它們是短邏輯塊,作為內聯參數傳遞給更高階函數。通常,它們對于傳遞給它們的函數是唯一的,因此不需要具有名稱(匿名)的整個開銷。
有了它,我們可以實現類似于排序,映射,過濾等的構造,這些構造在JavaScript等語言中很容易實現:
[1,2,3,4].map(x => x*x).filter(x => x % 2 === 1).sort((a,b) => b - a)
C++中的代碼并不簡潔,但結構相同。來自std庫的許多函數式編程助手以半開間隔運行,這意味著包括較低范圍,排除較高范圍。
// @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";
}
匿名函數的語法是在C++中習慣的東西。它們由括號指定,后跟參數列表,如[](int a,int b) - > bool {return a> b; }
。請注意,- > bool
指定一個布爾返回值。通常,您可以避免表達返回類型,因為它可以從函數體中的返回類型推斷出來。
如果要使用lambda函數之外的作用域中定義的變量,則需要進行變量捕獲。還有可能通過引用或值將參數傳遞給您的函數。
&
字符啟動lambda(就像在函數中使用引用時一樣):[&]
=
字符:[=]
還可以通過值和參考來混合和匹配捕獲。
例如,[=,&foo]
將為除foo
之外的所有變量創建副本,這些變量通過引用捕獲。
它有助于理解使用lambdas時幕后發生的事情:
事實證明,lambdas的實現方式是創建一個小類;這個類重載了operator()
,因此它就像一個函數一樣。lambda函數是這個類的一個實例;構造類時,周圍環境中的任何變量都將傳遞給lambda函數類的構造函數并保存為成員變量。事實上,這有點像已經可能的仿函數的想法。C++ 11的好處是,這樣做變得非常簡單——所以你可以一直使用它,而不是僅僅在非常罕見的情況下編寫一個全新的類是有意義的。
Lambda函數在EOS智能合約中大量使用,因為它們提供了一種非常方便的方法來修改少量代碼中的數據。標準庫中有更多函數,它們與我們在sort
,transform
,remove_if
和find_if
中看到的函數類似。它們都通過<algorithm>
標頭導出。
======================================================================
分享一些比特幣、以太坊、EOS等區塊鏈相關的交互式在線編程實戰教程:
- EOS入門教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智能合約開發與部署、使用代碼與智能合約交互等核心知識點,最后綜合運用各知識點完成一個便簽DApp的開發。
- 深入淺出玩轉EOS錢包開發,本課程以手機EOS錢包的完整開發過程為主線,深入學習EOS區塊鏈應用開發,課程內容即涵蓋賬戶、計算資源、智能合約、動作與交易等EOS區塊鏈的核心概念,同時也講解如何使用eosjs和eosjs-ecc開發包訪問EOS區塊鏈,以及如何在React前端應用中集成對EOS區塊鏈的支持。課程內容深入淺出,非常適合前端工程師深入學習EOS區塊鏈應用開發。
- java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Java代碼中集成比特幣支持功能,例如創建地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
- php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Php代碼中集成比特幣支持功能,例如創建地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
- c#比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在C#代碼中集成比特幣支持功能,例如創建地址、管理錢包、構造裸交易等,是C#工程師不可多得的比特幣開發學習課程。
- java以太坊開發教程,主要是針對java和android程序員進行區塊鏈以太坊開發的web3j詳解。
- python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
- php以太坊,主要是介紹使用php進行智能合約開發交互,進行賬號創建、交易、轉賬、代幣開發以及過濾器和交易等內容。
- 以太坊入門教程,主要介紹智能合約與dapp應用開發,適合入門。
- 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
- ERC721以太坊通證實戰,課程以一個數字藝術品創作與分享DApp的實戰開發為主線,深入講解以太坊非同質化通證的概念、標準與開發方案。內容包含ERC-721標準的自主實現,講解OpenZeppelin合約代碼庫二次開發,實戰項目采用Truffle,IPFS,實現了通證以及去中心化的通證交易所。
- C#以太坊,主要講解如何使用C#開發基于.Net的以太坊應用,包括賬戶管理、狀態與交易、智能合約開發與交互、過濾器和交易等。
- Hyperledger Fabric 區塊鏈開發詳解,本課程面向初學者,內容即包含Hyperledger Fabric的×××書與MSP服務、權限策略、通道配置與啟動、鏈碼通信接口等核心概念,也包含Fabric網絡設計、nodejs鏈碼與應用開發的操作實踐,是Nodejs工程師學習Fabric區塊鏈開發的最佳選擇。
- Hyperledger Fabric java 區塊鏈開發詳解,課程面向初學者,內容即包含Hyperledger Fabric的×××書與MSP服務、權限策略、頻道配置與啟動、鏈碼通信接口等核心概念,也包含Fabric網絡設計、java鏈碼與應用開發的操作實踐,是java工程師學習Fabric區塊鏈開發的最佳選擇。
- tendermint區塊鏈開發詳解,本課程適合希望使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI接口、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操代碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。
匯智網原創翻譯,轉載請標明出處。這里是C++開發EOS基礎指南:迭代器和Lambda表達式
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。