C_and_CPP 板


LINE

本文大部份內容來自此網頁: C++ Has Become More Pythonic http://preshing.com/20141202/cpp-has-become-more-pythonic/ --------------------------- 我以前也是覺得C++的語法看起來很複雜很討厭的人。 不過C++這幾年變了很多,C++11 和 C++14 加了很多新語法進去。 連C++的老爸 Bjarne Stroustrup http://www.stroustrup.com/C++11FAQ.html#think 都說: “It feels like a new language.” 該怎麼說呢?語法上愈來愈簡潔,愈來愈python化了... 不知道是python影響C++還是C++影響python? 以下就大致列出python跟C++的共同點。 ### 語法 (Literals) ### Python從2008年開始引進字面輸入二進位值(binary literals)。 gcc從2007年就支援(雖然C standard從來沒把這個加進去)。 C++是直到C++14 http://en.cppreference.com/w/cpp/language/integer_literal 才正式支援: static const int primes = 0b1010000010001010001010; 當字串中有**'\\'**的時候,以前你可能得這樣寫: const char* path = "(c:\\this\\string\\has\\backslashes)"; C++11 http://en.cppreference.com/w/cpp/language/string_literal 開始可以字面輸入原始字串(raw string literals)。 const char* path = R"(c:\this\string\has\backslashes)"; Python則是1998年就支援了。 ### 有範圍根據的 for 迴圈(Range-Based For Loops) ### Python裡要在同一個物件裡用迴圈把其中元素一一取出的話很簡單: for x in myList: print(x) 古早的C++寫起來很累贅 // array for (int i=0; i<10; ++i) std::cout<< A[i] << ' '; // vector(我討厭這種寫法...) for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) { /* std::cout << *it; ... */ } http://en.cppreference.com/w/cpp/language/range-for C++11開始你就能優雅地寫for loop: std::vector<int> v = {0, 1, 2, 3, 4, 5}; for(const int &i : v) // access by const reference std::cout << i << ' '; std::cout << '\n'; for(auto i: v) // access by value, the type of i is int std::cout << i << ' '; std::cout << '\n'; for(auto&& i: v) // access by reference, the type of i is int& std::cout << i << ' '; std::cout << '\n'; for(int n: {0, 1, 2, 3, 4, 5}) // the initializer may be a braced-init-list std::cout << n << ' '; std::cout << '\n'; int a[] = {0, 1, 2, 3, 4, 5}; for(int n: a) // the initializer may be an array std::cout << n << ' '; std::cout << '\n'; for(int n: a) std::cout << 1 << ' '; // the loop variable need not be used std::cout << '\n'; ### 自動指定型別 Auto ### Python有個方便的地方就是不用理會變數到底該用怎樣的型別(data type), 會自動幫你決定或改變。 C++以前可不是這樣,但是C++11 http://en.cppreference.com/w/cpp/language/auto 開始多了自動推斷類型的語法: auto x = "Hello world!"; std::cout << x; 就算是有函式重載(function overloading)的情況下, 呼叫函式時編譯器也會對於auto自動判別的型別指到相對應的函式去。 C++14更方便,連自動決定函式的回傳型別(Function return type deduction) https://en.wikipedia.org/wiki/C%2B%2B14#Function_return_type_deduction 都能辦到了。 auto Correct(int i) { if (i == 1) return i; // return type deduced as int else return Correct(i-1)+i; // ok to call it now } auto Wrong(int i) { if (i != 1) return Wrong(i-1)+i; // Too soon to call this. No prior return statement. else return i; // return type deduced as int } ### Tuples ### Python很久就有tuple這個能把不同型別的變數包在一起又不能修改的型別。 triple = (5, 6, 7) print(triple[0]) C++11開始也有了,甚至直接挑明這是跟Python致敬。 auto triple = std::make_tuple(5, 6, 7); std::cout << std::get<0>(triple); Python可以把tuple拆開 x, y, z = triple C++11當然也可以 std::tie(x, y, z) = triple; ### 統一初始化 (Uniform Initialization) ### Python可以當初始一個List類型時就把元素加進去,之後想增加也行。 Dictionary也可以這樣搞。 myList = [6, 3, 7, 8] myList.append(5); myDict = {5: "foo", 6: "bar"} print(myDict[5]) C++11 http://www.stroustrup.com/C++11FAQ.html#init-list 開始, vector、std::map 和 unordered_map也可以這樣搞了 auto myList = std::vector<int>{ 6, 3, 7, 8 }; myList.push_back(5); auto myDict = std::unordered_map<int, const char*>{ { 5, "foo" }, { 6, "bar" } }; std::cout << myDict[5]; ### Lambda 表達式 (Lambda Expressions) ### Python的Lambda是很神奇的東西... myList.sort(key = lambda x: abs(x)) C++11 http://www.stroustrup.com/C++11FAQ.html#lambda 居然也有了... (可我還是比較喜歡函式指標阿....) std::sort(myList.begin(), myList.end(), [](int x, int y){ return std::abs(x) < std::abs(y); }); ### Standard Algorithms ### Python可以用內建的filter函式把符合條件的元素複製出來... result = filter(lambda x: x >= 0, myList) C++11 http://en.cppreference.com/w/cpp/algorithm/copy 的 std::copy_if有著相似的功能... (怎麼突然有種好神奇的感覺?) auto result = std::vector<int>{}; std::copy_if(myList.begin(), myList.end(), std::back_inserter(result), [](int x){ return x >= 0; }); ### Parameter Packs ### Python這個功能我還真沒用過,實際用法可以參考這裡 http://hangar.runway7.net/python/packing-unpacking-arguments def func1(x, y, z): print x print y print z def func2(*args): # Convert args tuple to a list so we can modify it args = list(args) args[0] = 'Hello' args[1] = 'awesome' func1(*args) func2('Goodbye', 'cruel', 'world!') # Will print # > Hello # > awesome # > world! C++11 也能這樣做 http://www.stroustrup.com/C++11FAQ.html#variadic-templates template <typename... T> auto foo(T&&... args) { return std::make_tuple(args...); } ... auto triple = foo(5, 6, 7); 看到這裡,是不是覺得C++變得愈來愈優雅了? --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 90.41.1.211
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_and_CPP/M.1462301210.A.9FC.html ※ 編輯: wtchen (90.41.1.211), 05/04/2016 02:56:44
1F:推 james732: 推 05/04 09:26
2F:推 Frozenmouse: 說到 param pack,昨天好奇去看了C++17 的 fold expr 05/04 10:06
3F:→ Frozenmouse: 覺得這語法超神奇的XDDD 05/04 10:06
4F:→ Frozenmouse: C++在這幾年真的是不斷進化,都快不認識了 05/04 10:07
5F:→ Neisseria: 建議板大連結不要放括號裡,會帶到瀏覽器,造成錯誤 05/04 10:28
拿掉了,因為本來是用kramdown寫的。
6F:推 prismwu: 這篇不錯耶 05/04 10:44
7F:推 exeex: 推 for 對 vector的用法太實用了 05/04 10:51
8F:→ bibo9901: 老實說你講的這幾點都不是python獨有/獨創 05/04 11:28
9F:→ uranusjr: 沒人說這些是 Python 獨有/創新, 但 Python 是極少數擁 05/04 14:11
10F:→ uranusjr: 有「全部」的語言 -- 現在 C++ 也加入這個榮譽俱樂部了 05/04 14:11
11F:→ uranusjr: 希望 C++ 未來也能有 enhanced proposal 機制 05/04 14:13
12F:→ uranusjr: (打錯, 是 enhancement proposal) 05/04 14:13
13F:→ freeunixer: lambda 是從 fp 來的,最早在 lisp 就已經有了. 05/04 14:33
14F:→ freeunixer: Java 是從 8 開始才有,但基本上現在的 Python, 05/04 14:33
15F:→ freeunixer: 對 lambda 依賴已經沒有以前高,用型別運算產生式就行. 05/04 14:34
16F:→ freeunixer: 另外,以前蔡學鏞推過一個 rebol.不過這幾年沒啥進步.. 05/04 14:38
17F:→ freeunixer: 如果對 C++ 難分難捨,那也許也可以留意一下 Rust 05/04 14:39
※ 編輯: wtchen (90.41.1.211), 05/04/2016 15:27:43
18F:→ wtchen: 有大大可以寫篇Rust跟C++的比較文嗎?保證不砍 05/04 15:37
19F:推 bibo9901: 說得也是 05/04 15:58
20F:推 CoNsTaR: 推 Rust 05/04 15:59
21F:→ freeunixer: Parameter Packs 其實就是未指定參數名稱,就都算它的. 05/04 16:25
22F:→ freeunixer: 比如 x= ,y= , a,b,c ,沒有 = 指定輸入值,就全給 *arg 05/04 16:26
23F:→ freeunixer: 所以 func1 把 arg 前兩個換掉再丟進 func2 去配對. 05/04 16:31
24F:→ freeunixer: 2 1 05/04 16:32
25F:→ freeunixer: 一般看到的範例是 func1(x, *args) 這種型式. 05/04 16:34
26F:→ freeunixer: 沒被指定參數名稱抓到的,就全送進 *arg 05/04 16:34
27F:→ wtchen: C++11之後,C跟C++的分歧就越來越大了.... 05/04 16:36
28F:→ bibo9901: 其實可以更徹底一點XD 為了兼容C實在犧牲太大了.. 05/04 16:38
29F:→ freeunixer: python 3.x 還有 **args 抓進去直接配成 dict 的 k:v 05/04 16:43
30F:推 Frozenmouse: 與C相容…前朝遺毒 (誤 05/04 17:16
31F:推 Bencrie: 應該說...歷史包袱(? 05/04 21:38
32F:推 tuyutd0505: 推 有些寫法第一次看到 學習了 05/04 21:56
33F:推 laba5566: 推 05/04 22:43
34F:推 fanntone: C++11之後就是突破大氣層的感覺 05/04 23:45
35F:推 loveflames: final跟override也不錯 05/05 00:11
36F:推 loveflames: variadic template搭配多重繼承也蠻有趣的 05/05 00:17
37F:推 shaopin: for(auto&& i: v) // access by reference, the type of 05/05 04:38
38F:→ shaopin: 對這個有點問題, 如果auto&& 是by reference 那auto&呢? 05/05 04:38
39F:推 red0210: 推 寫得很棒 05/05 07:18
40F:推 loveflames: auto&&產生ref,auto&產生左值ref 05/05 07:53
41F:→ x000032001: 偷推yoco大神的文章 #19gioP8j 05/05 10:51
42F:推 Sylveon: 大推~ 05/05 12:01
43F:推 CoNsTaR: auto&&產生型態為右值ref的左值ref 05/05 12:07
44F:→ CoNsTaR: auto&參考到一個左值 不產生新物件 05/05 12:08
45F:→ Caesar08: auto &是l value ref,auto &&是r value ref 05/05 12:22
46F:推 loveflames: 不對,auto&&不是專門用在rvalue ref 05/05 12:33
47F:→ loveflames: 其中有用到跟template一樣的折疊規則 05/05 12:34
48F:→ Caesar08: 對不起,我錯了。有具名的&&才是r value ref。auto &&是 05/05 12:45
49F:→ Caesar08: forwarding reference 05/05 12:45
50F:→ Caesar08: 簡單來說,auto &&i:v要看v是l value還是r value。如果 05/05 12:47
51F:→ Caesar08: v是l value,那auto &&i就是int &i;如果 05/05 12:47
52F:→ Caesar08: v是r value,那auto &&i就是int &&i 05/05 12:48
53F:推 shaopin: 請問什麼是有具名的&&? 05/05 16:02
54F:→ Caesar08: 應該說,有具型態的才對。例如直接指定int &&,此時已經 05/05 16:09
55F:→ Caesar08: 指定型態是int,而不是用auto幫你進行type deduction 05/05 16:10
56F:推 loveflames: 注意const auto&&不適用折疊規則,此時就是rvalue ref 05/05 16:36
57F:→ loveflames: 跟template的推導規則一樣 05/05 16:36
58F:推 CoNsTaR: 簡單的說,reference to rvalue 本身也是一個 lvalue 05/05 17:46
59F:推 suhorng: auto 跟重載那段有點怪, 這兩個沒關聯吧 05/05 19:01
60F:→ suhorng: Python lambda 的語法限制有點詭異. Python 不太推lambda 05/05 19:03
61F:→ wtchen: 我自己是不太喜歡用lambda,太簡化的東西反而反應不過來 05/05 19:04
62F:→ suhorng: parameter pack 跟 variadic template 很不同吧? 05/05 19:05
63F:→ Caesar08: A template with at least one parameter pack is 05/05 19:19
64F:→ Caesar08: called a variadic template. 05/05 19:19
65F:推 loveflames: STL如果沒lambda,functor寫起來會很痛苦 05/05 19:45
66F:推 ronin728: Python也只是跟別人學來的,C++剛好學到一樣的部分而已z 05/06 11:17
67F:→ ronin728: 這些特性早在Ada,ML,Scheme就有了,他們都比Python老=.= 05/06 11:23
68F:推 Frozenmouse: 現代程式語言不都互相影響嗎,真要考古誰原創考不完w 05/06 16:30
69F:推 os653: 只求好寫、好偵錯、速度快又不用造輪子,誰抄誰不重要 05/06 19:34
70F:推 ho83leo: 推整理 05/07 22:39
71F:推 eye5002003: 好文!匿名函式這招實在太好用 05/07 22:41
72F:推 rodion: 推... 希望C++17把平行化也好好的弄出來:> 05/08 01:46
73F:推 fr3ak: 跟 Python 背景的朋友聊天講到 C++ Templates 的時候, 常以 05/16 02:53
74F:→ fr3ak: compile-time dock-type 類比 05/16 02:53







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Tech_Job站內搜尋

TOP