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/cn.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灯, 水草

请输入看板名称,例如:e-shopping站内搜寻

TOP