y******3 发帖数: 3 | 1 先立个flag, 从此以后有三不聊:不聊政治,不聊宗教,不聊教育孩子。这三个主题
有个共同的特点:大家都有自己的观点,大家都认为自己的观点对,但是其实谁的观点
还都没啥用!而且这些话题插嘴的门槛还特别底, 这就是为啥容易吵吵起来的原因了。
所以我决定聊点C++语言,不好意思,这个热心网友想插嘴还不太容易。 今天主要聊聊
我最近发现的C++的一个现象:那就是模板看起来很难, 其实不难; 异常看起来很简
单,其实很难;多线程看起来很难,其实TMD更难。
首先聊模板,talk is cheap,show me the code。下面这段眼花缭乱的代码要是读懂
还真不容易,不过他难就难在了语法上,其实就是利用编译期间,模板实例化的时候的
SFINAE特点,来判定一个类是否有serialize这个函数。就这么简单。我知道你想骂人
了,好端端的你就直接说中文就好,为啥总拽洋文呢? 因为这个词一旦翻译成中文,
你要是看到了就想打人了。 这个单词就是“替换失败不是错误”这几个词的首字母缩
写。不知道你怎么想,我个人觉得,同样是不懂,但是英文说出来更牛逼一点,是不?
template struct hasSerialize{
typedef char yes[1];
typedef yes no[2];
template struct reallyHas;
template static yes& test(reallyHas* /unused/) { }
template static no& test(…) { /* dark matter */ }
static const bool value = sizeof(test(0)) == sizeof(yes);
};
std::cout << hasSerialize::value << std::endl;
至于语法上花了呼哨的,其实就是一个习惯的问题,一旦你习惯了这种语法,你再看
hello world啥的还觉得别扭呢! 好了总结一下,模板编程大部分都是语法上叠屋架床
的,其实语义层面相当直接和简单。抓住了语义,那就是一拳到肉。至于语法开始麻烦
点,大不了面向stack overflow编程就好。对了提醒一下,一般stack overflow上分为
提问区和解答区,抄代码的时候一定要从解答区copy! 看看,这就是一拳到肉!
聊完了模板,现在聊聊异常,介绍C++异常的时候通常都会提到一个小函数,这个函数
就是assert。这个函数简单的不得了,就是输入一个判断bool的表达式,如果表达式为
false, 那么assert就终止整个程序。好吧,上代码:
assert(2+2==4);
就这么简单吗?对,就这么简单。那么下一个问题就来了,判断表达式判断啥?,
assert该在哪里用呢?嗯~~, 这个depends。
我知道你又想打人了,刚刚明白了上面比较复杂的语法,现在好不容易遇到一个简单的
,就是想知道在哪里用,你还说depends。这种感觉就像你把500块钱刚给了大街上一位
向你招手的女孩,女孩收下钱后马上对你说你是一个好人。这就是一种想打人的感觉。
好吧,我换一种说法,assert就是用来验证是否违背了(invariant)不变性的时候用
的。你现在感觉好点了吗? OK,那么什么又是(invariant)不变性呢? 举个例子吧
,你今年20,再过一年你21,你遵守了(invariant)不变性,如果你今年20,过一年
你还是20,那么你破坏了(invariant)不变性。来吧,打我啊!
没错,你没看错,(invariant)不变性其实是一个更大的概念,它就是指程序在语义
上面是正确的,过了一年长一岁,这个在逻辑语义上是对的。 或者在一个更大的范围
内是正确并且稳定的。例如,王健林为了让你完成一个小目标,给你转了一个亿。 在
王健林的钱离开他的账号,但是还没到你的账号的时候,你们之间的(invariant)不
变性就被打破了,直到钱转到你的账号上,你们之间的(invariant)不变性就又恢复
了。不变性并不是指的“不变性”。验证这种(invariant)不变性其实是对编程以外
的领域知识要非常了解的。例如:对一个人员管理系统,你应该用下面的assert语句。
问题是,你真的确定100是正确的吗?你对全世界人口的极大值了解吗?
assert(age>0)
assert(age<100),
哪里会破坏(invariant)不变性呢,这个在多线程里面最多了。例如如果我们有两个
线程分别计算你的岁数,每个线程把你的年龄加上0.5,这个时候如果同步的不对,就
会发生data race。例如一个线程读入20,加上0.5后,还没写入到内存的时候,另外一
个线程切入,读入20,加上0.5后,写回到内存。这个时候第一个线程再次回归,把自
己计算得到的20.5再写一遍内存。最后两个线程结束后,内存里保存的就是20.5,而不
是21了。这个时候你已经违背了(invariant)不变性了。
除了容易发生违背了(invariant)不变性以外,多线程另外一个问题就是语法和语义
都很难,大量的模板推高了使用线程的语法的难度。语义上,哪怕一个简单的锁,什么
时候用?哪里用?用不用?通通depends。 原子编程的内存模型又把语义方面的知识推
到了CPU的instrument那个层次上去了。
上面说到多线程非常容易破坏数据的(invariant)不变性,首先这种破坏通常很难调
试,因为他们并不是每次复现。另外破坏数据的(invariant)不变性还有一个更糟糕
的结果,那就是程序的行为“未定义”。
C++新手看到“未定义”这一个词通常会有一种乐观的情绪。他们刚被“面向对象”糊
弄到编程这个领域,既然是“未定义”,那么也许是“洞房花烛夜”也保不齐。一般C+
+老手会告诫新手,未定义通常是“洞房花烛夜-不举”。而10年以上的老鸟会说:未定
义通常是“洞房花烛夜-新娘不举”。20年以上的骨灰这个时候一般是不说话的,他们
一般45度斜头上望,眼睛里留下两行浊泪,嘴里嘟囔着:“那一年,我洞房花烛夜-新
娘很举”。
希望你们能通过这个故事记住“未定义”这个词。对这个词到底有多坏一定要有充足的
想象力。说简单点,标准委员会也不知道某些行为会坏到什么程度,那就叫做“未定义
”吧。就像一个人长的丑得他妈都不愿意看,那么这种丑就叫做“未定义”。
总结一下:
1)模板在唬人的语法下面其实挺简单的,理解了它到底要干什么,那就一拳到肉了。
2)遇到depends的时候,通常意味着你需要更深入的领域知识了。
3)能不用多线程就不用,必须要用就用成熟的线程库和模型,例如boost线程池库,生
产者-消费者模型,消息传递模型等。
4)如果你对“未定义”这个词感触不深,那么说明你还没到“那一年…” |
n******t 发帖数: 4406 | 2 C++的问题在于自己一直不知道自己要干什么。总想成为最牛逼的XXX。
自己搞了一堆的OOP,dynaming dispatching,被人说overhead 太高(which is true
,但是这个问题的根本来自于CPP标准库设计者的品味还不如python),立刻自忏形秽
,全面挪向template,一时间好像不用template都羞于见人的样子。搞完了发现居然一
个方法有没有都没法判断,OK,我们hack一个,全然不管这个句法有多恶心,和多不靠
谱。实际上这些人都意识到一个关键的问题,当你care一个function call的overhead
的时候,99%的情况下,你根本不应该去考虑这些莫名其妙的事情。
template搞完了,然后听说并行火了,又开始狂塞thread library,结果C++的thread
和exception搞到一起一堆烂事。
反正就是怎么时髦跟什么,就瞎加功能,完全不考虑自己要claim的事情,自己的基本
条件具备不具备最后就成这样了。
了。
【在 y******3 的大作中提到】 : 先立个flag, 从此以后有三不聊:不聊政治,不聊宗教,不聊教育孩子。这三个主题 : 有个共同的特点:大家都有自己的观点,大家都认为自己的观点对,但是其实谁的观点 : 还都没啥用!而且这些话题插嘴的门槛还特别底, 这就是为啥容易吵吵起来的原因了。 : 所以我决定聊点C++语言,不好意思,这个热心网友想插嘴还不太容易。 今天主要聊聊 : 我最近发现的C++的一个现象:那就是模板看起来很难, 其实不难; 异常看起来很简 : 单,其实很难;多线程看起来很难,其实TMD更难。 : 首先聊模板,talk is cheap,show me the code。下面这段眼花缭乱的代码要是读懂 : 还真不容易,不过他难就难在了语法上,其实就是利用编译期间,模板实例化的时候的 : SFINAE特点,来判定一个类是否有serialize这个函数。就这么简单。我知道你想骂人 : 了,好端端的你就直接说中文就好,为啥总拽洋文呢? 因为这个词一旦翻译成中文,
|
y******3 发帖数: 3 | 3
true
overhead
thread
高见!我再补充两点,其实C++有很沉重的历史包袱,必须要保证能够编译70年代诞生
的C语言代码。另外就是要保证不损失任何效率。 有这两个约束,就像带着镣铐跳舞,
舞姿就越来越离谱了。
【在 n******t 的大作中提到】 : C++的问题在于自己一直不知道自己要干什么。总想成为最牛逼的XXX。 : 自己搞了一堆的OOP,dynaming dispatching,被人说overhead 太高(which is true : ,但是这个问题的根本来自于CPP标准库设计者的品味还不如python),立刻自忏形秽 : ,全面挪向template,一时间好像不用template都羞于见人的样子。搞完了发现居然一 : 个方法有没有都没法判断,OK,我们hack一个,全然不管这个句法有多恶心,和多不靠 : 谱。实际上这些人都意识到一个关键的问题,当你care一个function call的overhead : 的时候,99%的情况下,你根本不应该去考虑这些莫名其妙的事情。 : template搞完了,然后听说并行火了,又开始狂塞thread library,结果C++的thread : 和exception搞到一起一堆烂事。 : 反正就是怎么时髦跟什么,就瞎加功能,完全不考虑自己要claim的事情,自己的基本
|
C*****l 发帖数: 1 | 4 你这个sample是valid code 么? 为什么用template没有看到尖括号 |
n******t 发帖数: 4406 | 5 当年和BS一个办公室的人给我说过,他和Ken Thompson关系不咋个,主要就是因为BS想
把CPP搞成最牛逼的语言,什么都牛逼,但是Ken觉得他那些东西都没啥用,所以关系就不
行了。
从某个角度来说,BS其实根本不想要C,因为他非常ambitious。但是他没办法,他也知
道他的东西不靠C没机会,which这是他成功的唯一原因。CPP的OOP设计在一堆语言里面
算非常普通,标准库的实现水平算中下的,STL出来之后勉强可以算中等。所以这个历
史包袱,某个角度来来说也是it的基本盘。当年有很多C程序员,想去学一下OOP的时候
,没有任何道理地选择了C++就是这个原因。
这就是为什么,CPP在很长一段时间,没有人用it的标准库的原因,要不就用C,要不就
用平台提供的一堆库,在Windows下面就是MFC,其实除了GUI toolkit之外就是用用
Cstring之类的东西。Unix下面很长一段时间,用C++写不出来能用的程序,除了装模作
样的写几个class,继承一下,显得自己OOP了之外,啥也干不了。这事情直到大部分平
台都有STL之后才有所好转,但是这个时候已经有Java,C#这一堆东西了。而且这些人
始终没搞明白,nobody cares那些个static polymorphism的trick,人要的,只是一个
能随便扔元素的vector,一个hashtable,没了(连tree其实都没人用)。真的care
static 和dynamic polymorphism的性能差别的人,不会用STL的。
【在 y******3 的大作中提到】 : : true : overhead : thread : 高见!我再补充两点,其实C++有很沉重的历史包袱,必须要保证能够编译70年代诞生 : 的C语言代码。另外就是要保证不损失任何效率。 有这两个约束,就像带着镣铐跳舞, : 舞姿就越来越离谱了。
|
l**********3 发帖数: 1 | 6 There are only two kinds of languages: the ones people complain about and
the ones nobody uses.
就不
【在 n******t 的大作中提到】 : 当年和BS一个办公室的人给我说过,他和Ken Thompson关系不咋个,主要就是因为BS想 : 把CPP搞成最牛逼的语言,什么都牛逼,但是Ken觉得他那些东西都没啥用,所以关系就不 : 行了。 : 从某个角度来说,BS其实根本不想要C,因为他非常ambitious。但是他没办法,他也知 : 道他的东西不靠C没机会,which这是他成功的唯一原因。CPP的OOP设计在一堆语言里面 : 算非常普通,标准库的实现水平算中下的,STL出来之后勉强可以算中等。所以这个历 : 史包袱,某个角度来来说也是it的基本盘。当年有很多C程序员,想去学一下OOP的时候 : ,没有任何道理地选择了C++就是这个原因。 : 这就是为什么,CPP在很长一段时间,没有人用it的标准库的原因,要不就用C,要不就 : 用平台提供的一堆库,在Windows下面就是MFC,其实除了GUI toolkit之外就是用用
|
p*****n 发帖数: 64 | 7 楼主辛苦了。
不敢沟通template简单。简单地用template的确简单,甚至有些简单的推导都还行。一
旦复杂了,看代码就是相当地累,因为从一个函数根本一眼看不出来会调用哪个子函数
。要推导就必须从最上头开始查找,然后分析出当前的参数和参数的定义,再推导最终
的子函数
了。
【在 y******3 的大作中提到】 : 先立个flag, 从此以后有三不聊:不聊政治,不聊宗教,不聊教育孩子。这三个主题 : 有个共同的特点:大家都有自己的观点,大家都认为自己的观点对,但是其实谁的观点 : 还都没啥用!而且这些话题插嘴的门槛还特别底, 这就是为啥容易吵吵起来的原因了。 : 所以我决定聊点C++语言,不好意思,这个热心网友想插嘴还不太容易。 今天主要聊聊 : 我最近发现的C++的一个现象:那就是模板看起来很难, 其实不难; 异常看起来很简 : 单,其实很难;多线程看起来很难,其实TMD更难。 : 首先聊模板,talk is cheap,show me the code。下面这段眼花缭乱的代码要是读懂 : 还真不容易,不过他难就难在了语法上,其实就是利用编译期间,模板实例化的时候的 : SFINAE特点,来判定一个类是否有serialize这个函数。就这么简单。我知道你想骂人 : 了,好端端的你就直接说中文就好,为啥总拽洋文呢? 因为这个词一旦翻译成中文,
|
p*****n 发帖数: 64 | 8 不完全同意。c语言本身没有标准库,c++设计也就没有标准库。c++是最灵活的语言,
也是因为这个灵活让库设计付出了惨重的代价。
比如流设计,其远不如c语言的函数printf简单好用
后面template流行后,设计库时又搞了大量的template库。从代码量上是否简单了,一
个std:sort可以操作vector,array,字符串,以及他们部分内容的排序。但是这个又
违背了另外一个原则,keep it simple。导致这些库用起来繁琐,有时因为非定制又效
率低了。于是开始不断增加语法来补充
就不
【在 n******t 的大作中提到】 : 当年和BS一个办公室的人给我说过,他和Ken Thompson关系不咋个,主要就是因为BS想 : 把CPP搞成最牛逼的语言,什么都牛逼,但是Ken觉得他那些东西都没啥用,所以关系就不 : 行了。 : 从某个角度来说,BS其实根本不想要C,因为他非常ambitious。但是他没办法,他也知 : 道他的东西不靠C没机会,which这是他成功的唯一原因。CPP的OOP设计在一堆语言里面 : 算非常普通,标准库的实现水平算中下的,STL出来之后勉强可以算中等。所以这个历 : 史包袱,某个角度来来说也是it的基本盘。当年有很多C程序员,想去学一下OOP的时候 : ,没有任何道理地选择了C++就是这个原因。 : 这就是为什么,CPP在很长一段时间,没有人用it的标准库的原因,要不就用C,要不就 : 用平台提供的一堆库,在Windows下面就是MFC,其实除了GUI toolkit之外就是用用
|
l**********3 发帖数: 1 | 9 c++的各种毛病归根到底就是缺乏象龟叔这样"仁慈的独裁者", 想让各方都满意, 结果
谁都不满意. |
n******t 发帖数: 4406 | 10 C stdlib是标准的一部分,不知道你为什么觉得C没有标准库。
说到iostream这个东西,exactly体现了CPP 库设计的糟糕之处:为了某个功能或者是
修改某个别的语言的短板,放弃掉了一堆的好处。它其实唯一的优势是printf需要
explicit
指明type比较麻烦,但是却完全改变了printf输出最重要的特性,模版。某个角度上来
说,这个是perfect的直观,但是却没效率也不好用的设计典型。这种思维方式,我如
果招程序员的时候一定会避免掉。实际上要弥补那个不足需要的只是给一个auto
format specifier而已。
C的qsort也是什么类型都可以操作的。此外C一样可以meta programming,用宏就可以。
【在 p*****n 的大作中提到】 : 不完全同意。c语言本身没有标准库,c++设计也就没有标准库。c++是最灵活的语言, : 也是因为这个灵活让库设计付出了惨重的代价。 : 比如流设计,其远不如c语言的函数printf简单好用 : 后面template流行后,设计库时又搞了大量的template库。从代码量上是否简单了,一 : 个std:sort可以操作vector,array,字符串,以及他们部分内容的排序。但是这个又 : 违背了另外一个原则,keep it simple。导致这些库用起来繁琐,有时因为非定制又效 : 率低了。于是开始不断增加语法来补充 : : 就不
|
C*****l 发帖数: 1 | 11 对,这个iostream特别难用,多打无数的《,把一句完整的string搞得支离破碎。别的
语言比如python的string format其实是老C的路线。 iterator begin end也特别难用
,sort也非要搞个range。感觉committe的设计都是傻大笨粗。
题有个共同的特点:大家都有自己的观点,大家都认为自己的观点对,但是其实谁的观
点还都没啥用!而且这些话题插嘴的门槛还特别底, 这就是为啥容易吵吵起来的原因
了。
聊我最近发现的C 的一个现象:那就是模板看起来很难, 其实不难; 异常看起来很
简单,其实很难;多线程看起来很难,其实TMD更难。
懂还真不容易,不过他难就难在了语法上,其实就是利用编译期间,模板实例化的时候
的SFINAE特点,来判定一个类是否有serialize这个函数。就这么简单。我知道你想骂
人了,好端端的你就直接说中文就好,为啥总拽洋文呢? 因为这个词一旦翻译成中文
,你要是看到了就想打人了。 这个单词就是“替换失败不是错误”这几个词的首字母
缩写。不知道你怎么想,我个人觉得,同样是不懂,但是英文说出来更牛逼一点,是不?
【在 y******3 的大作中提到】 : 先立个flag, 从此以后有三不聊:不聊政治,不聊宗教,不聊教育孩子。这三个主题 : 有个共同的特点:大家都有自己的观点,大家都认为自己的观点对,但是其实谁的观点 : 还都没啥用!而且这些话题插嘴的门槛还特别底, 这就是为啥容易吵吵起来的原因了。 : 所以我决定聊点C++语言,不好意思,这个热心网友想插嘴还不太容易。 今天主要聊聊 : 我最近发现的C++的一个现象:那就是模板看起来很难, 其实不难; 异常看起来很简 : 单,其实很难;多线程看起来很难,其实TMD更难。 : 首先聊模板,talk is cheap,show me the code。下面这段眼花缭乱的代码要是读懂 : 还真不容易,不过他难就难在了语法上,其实就是利用编译期间,模板实例化的时候的 : SFINAE特点,来判定一个类是否有serialize这个函数。就这么简单。我知道你想骂人 : 了,好端端的你就直接说中文就好,为啥总拽洋文呢? 因为这个词一旦翻译成中文,
|
p*****n 发帖数: 64 | 12 我说的是设计语言时。70年代设计c语言并没有设计一套标准库。c的库主要来自unix。
然后不同系统上移植c语言后发展了多个库变种。直到80年代才有标准c,然后也制定了
库标准。你要是在Windows和unix都做过就知道,很多时候库函数并不一致。
explicit
以。
言,
,一
个又
又效
【在 n******t 的大作中提到】 : C stdlib是标准的一部分,不知道你为什么觉得C没有标准库。 : 说到iostream这个东西,exactly体现了CPP 库设计的糟糕之处:为了某个功能或者是 : 修改某个别的语言的短板,放弃掉了一堆的好处。它其实唯一的优势是printf需要 : explicit : 指明type比较麻烦,但是却完全改变了printf输出最重要的特性,模版。某个角度上来 : 说,这个是perfect的直观,但是却没效率也不好用的设计典型。这种思维方式,我如 : 果招程序员的时候一定会避免掉。实际上要弥补那个不足需要的只是给一个auto : format specifier而已。 : C的qsort也是什么类型都可以操作的。此外C一样可以meta programming,用宏就可以。
|
c*******v 发帖数: 2599 | 13 其當然不可能與C/Unix的人有好的關係。
https://en.wikipedia.org/wiki/C%2B%2B
Wiki:
It certainly has its good points. But by and large I think it's a bad
language. It does a lot of things half well and it's just a garbage heap of
ideas that are mutually exclusive.
...
Stroustrup campaigned for years and years and years, way beyond any sort of
technical contributions he made to the language, to get it adopted and used.
----Ken THompson
就不
【在 n******t 的大作中提到】 : 当年和BS一个办公室的人给我说过,他和Ken Thompson关系不咋个,主要就是因为BS想 : 把CPP搞成最牛逼的语言,什么都牛逼,但是Ken觉得他那些东西都没啥用,所以关系就不 : 行了。 : 从某个角度来说,BS其实根本不想要C,因为他非常ambitious。但是他没办法,他也知 : 道他的东西不靠C没机会,which这是他成功的唯一原因。CPP的OOP设计在一堆语言里面 : 算非常普通,标准库的实现水平算中下的,STL出来之后勉强可以算中等。所以这个历 : 史包袱,某个角度来来说也是it的基本盘。当年有很多C程序员,想去学一下OOP的时候 : ,没有任何道理地选择了C++就是这个原因。 : 这就是为什么,CPP在很长一段时间,没有人用it的标准库的原因,要不就用C,要不就 : 用平台提供的一堆库,在Windows下面就是MFC,其实除了GUI toolkit之外就是用用
|
n******t 发帖数: 4406 | 14 我認為general purpose的編程語沒有完美的,所以語言設計是一門藝術而不是工程,
而藝術家最重要的是taste,BS的問題是taste非常差。
of
of
used.
【在 c*******v 的大作中提到】 : 其當然不可能與C/Unix的人有好的關係。 : https://en.wikipedia.org/wiki/C%2B%2B : Wiki: : It certainly has its good points. But by and large I think it's a bad : language. It does a lot of things half well and it's just a garbage heap of : ideas that are mutually exclusive. : ... : Stroustrup campaigned for years and years and years, way beyond any sort of : technical contributions he made to the language, to get it adopted and used. : ----Ken THompson
|