Re: 關於 stl 和 c++ 的一點問題

看板C_and_CPP作者 (髮箍)時間6年前發表 (2018/11/29 17:31), 6年前編輯推噓7(703)
留言10則, 9人參與, 6年前最新討論串2/3 (看更多)
哈囉, 如果你對 STL 有興趣的話可以參考下面的影片 (依序看): CppCon 2018: Jonathan Boccara “105 STL Algorithms in Less Than an Hour” https://youtu.be/2olsGf6JIkU
Stephan T. Lavavej - Standard Template Library (STL) https://bit.ly/2fS8u8c Stephan T Lavavej - Advanced STL https://bit.ly/2fS5lFF 其實 STL 粗略來分有 Algorithm 以及 Container 兩部分, 使用 Container 不只需要有部分資料結構的基礎, 也要知道 concept 這個觀念, 知道在 template 裡有對參數型別依賴哪些操作之後, 就可以進一步學習使用 Algorithm. Algorithm 架構在兩個基本 concept 之上 (當然其他還有很多): 1. iterator 2. range iterator (迭代器) 是類指標物件, 用來指向容器裡的物件, 你可 以用 operator++ 讓迭代器指向容器裡下個物件(概念上), 而不用 在意容器實際上是由什麼資料結構實作而來. range 這個概念最簡 單的描述就是: 有一個物件集合, 可以用兩個迭代器去描述, 其中一個 迭代器指向集合中的第一個物件, 另一個結束迭代器則 用來指向最後一個物件的後方. 你可以將開始迭代器不斷 地疊加, 直到它指向結束迭代器為止, 如此就完成尋訪集 合裡的所有物件. 以數學表示大概是 [first, last)這樣 的半開區間 (容器也會提供這樣成對的迭代器) 近年來 C++ Community 也在提倡多使用 Algorithm 來取代重複的 程式碼, 一方面可以提升可讀性, 另一方面也省去不必要的物件定 義. 以簡單的數偶數來說, 你可能會這樣寫: 1 std::array<int, 5> values{1, 2, 3, 4, 5}; 2 3 unsigned even = 0u; // what type should I use? 4 for (auto v : values) { 5 if (v % 2 == 0) { // core logic #1: operate on evens 6 ++even; // core logic #2: count things 7 } // #1 + #2: count evens 8 } 9 // 'even' finally available now 你會發現我們在第 3 行定義了 even 變數, 但是要到第 9 行它的 值才是有意義的, 然後必須將迴圈一層層分解看到第 6 行才能知 道它在作什麼, 這邊可以用 std::count_if() 來改寫: 1 auto const even = std::count_if( 2 std::begin(values), std::end(values), 3 [] (auto v) { return v % 2 == 0; } 4 ); 讀作: count from begin of values to end of values if v % 2 == 0 然後在 C++20 你可以進一步簡化 (或是用 Boost.Range): 1 auto const even = std::ranges::count_if( 2 values, [] (auto v) { return v % 2 == 0; } 3 ); 讀作: count all values if v % 2 == 0 使用 lambda 不僅可以清楚表達核心邏輯, 讀碼也可以較快切入重 點 參考資料: Working Draft (N4789) http://eel.is/c++draft/alg.count The One Ranges Proposal (P0896R3) https://bit.ly/2KGsMma -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.193.76.85 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1543512718.A.2BE.html

11/30 13:10, 6年前 , 1F
我到現在還是無法習慣這些用法
11/30 13:10, 1F

11/30 13:31, 6年前 , 2F
很遺憾的這是時代的趨勢 (C++ 以外的語言也有類似進化)
11/30 13:31, 2F

11/30 15:43, 6年前 , 3F
您是好人
11/30 15:43, 3F
騙騙 P 幣 xD

11/30 19:28, 6年前 , 4F
js圈會跟你說這是reactive programming
11/30 19:28, 4F

11/30 21:03, 6年前 , 5F
看不懂, 還是覺得第一種寫法好懂
11/30 21:03, 5F

11/30 21:04, 6年前 , 6F
而且任何語言用可以用
11/30 21:04, 6F
強烈建議搭配 Boost.Range Adaptor, 或是 range-v3 一起服用 range-v3 https://github.com/ericniebler/range-v3 Ranges for the Standard Library (N4128) https://bit.ly/2P7Zqh7

11/30 22:55, 6年前 , 7F
對最後一種最有感覺,短的程式碼比較容易懂?
11/30 22:55, 7F
差別在需要跳多深去 理解/修改 原始碼

11/30 23:08, 6年前 , 8F
先推 有空再來看影片
11/30 23:08, 8F

12/01 00:13, 6年前 , 9F
越長的程式碼越容易出錯
12/01 00:13, 9F

12/01 11:54, 6年前 , 10F
感謝分享
12/01 11:54, 10F
找個範例來演示: 從大到小印出整數範圍 [1, 100] 中所有 3 的倍數 有 range 及 view 的概念就可以讓程式碼 self-documented, 變 更需求成本就不會很高 (例如改成從小到大印出). 可惜 lambda 的語法偏複雜, 用 Boost.Range, Boost.Phoenix, Boost.Lambda 協作就會簡單很多. 至少我用 for 寫應該會讓人看不懂 xD auto result = irange(1, 100 + 1) | filtered(arg1 % 3 == 0) | reversed ; for_each(result, cout << _1 << " "); 連結: https://ideone.com/Yw3Fap ※ 編輯: poyenc (123.193.76.85), 12/01/2018 15:44:36
文章代碼(AID): #1FMSYlsg (C_and_CPP)
文章代碼(AID): #1FMSYlsg (C_and_CPP)