你们会向新人推荐 C++么?

2016 年 8 月 18 日
 xiqingongzi
/t/300012 提问 C++ 的路线图,很多人都在劝我放弃
但我是起意学 C++ 一方面是个人需要,另一方面是我的一个堂叔推荐我学 C++的。

什么样的情况下你会推荐别人学 C++ 。什么情况下不推荐 C++?

我觉得我堂叔不至于坑我吧....
13265 次点击
所在节点    C
174 条回复
FrankHB
2016 年 8 月 19 日
……很遗憾,随便逛了圈,发现 C 学傻的大概的确到处都是。
这里后面回复的大半楼几乎全能挂上: https://v2ex.ih06.com/t/298012
连 C 的 object 都不知道是什么还好意思装作会……再次表明 C 坑比 C++坑更危险。
Tyanboot
2016 年 8 月 19 日
@bombless 哈哈哈哈就是这种感觉,特别蛋疼但是又无奈,只能继续学下去。。
x8
2016 年 8 月 19 日
@FrankHB 在不清楚这个初学者以后到底要干什么的情况下, C 是性价比最高的语言。

用高级语言起手,会给初学者造成一种假象:底层那些复杂的弯弯绕已经被封装完美了,我们只要学会高级语言足够应付。

由俭入奢易,由奢入俭难。

殊不知高级语言那些名词会让初学者进入一个迷宫,继承,虚继承,虚表,函数指针,接口,值传递,引用传递,回调,委托,局部静态变量,协程,闭包。这些来自不同语言的概念,到底哪些本质上是一样的,或者说这种表现出来的特性,落实到 CPU 和内存上到底是怎么实现的?


作为工程派:
多线程竞争, volatile 关键字到底在影响什么, CPU cache 工作原理,以及一些以后可能会遇到的诡异 BUG ,甚至需要反汇编去搞清楚问题。如果只是疲于应付高级语言的概念,不了解底层实现,不能体会到程序编写其实就是”直接在一张白纸上写字“的感觉,那他对程序的理解也就止步于某一门语言中。 C 就是笔,最自由的一支笔,内存就是白纸,写什么,写上去的东西怎么理解,发生怎样的状态变化,产生什么行为,在 C 语言中是最直白清明的。当意识到面向对象与结构体还有函数指针关系的时候,才不会滥用设计模式。

作为学院派:
就算图灵机与λ演算是等价的,分别作为二者典型代表的 C 和 Lisp ,也明显是 C 的程序更符合初学者的思维方式,学完了这两门,其他语言都是在这两种语言之间做取舍。没有什么反面教材,一切的设计都是对解决问题的权衡,确实是有考虑不足的地方,但是不要局部不完美泛滥成整体否定。
Tyanboot
2016 年 8 月 19 日
扯点我自己的事情。本人今年高三毕业,报了计科。

如果要说我第一个学的是什么,就是 C++了,当时存粹是看了一眼姨妈贴上靠前的语言,然后从高一开始买了本书然后自学,当时只有微弱的 VB 基础,硬着头皮看了书,自己实践了实践,可以说是入门了,之后也是慢慢的看看资料,不懂的去请教大佬。

高二的时候又自学了 PHP ,因为有 C++的基础,感觉学起来特别快,一两个小时就搞懂了基本语法什么的,然后写了个小网站(表白墙)丢出去了。

前不久毕业了又学了点 C#,帮人做了个抓评论存 Excel 的工具。

而且都是因为有基础,理解其他的语言都挺快的,但是实际上感觉现在 C++已经基本不怎么接触了,除了在用到 Win32 的一堆 API 的时候,做 UI 的程序还是 C#来的快。

前不久还有几个同学来问我他也报了计科和软件工程,问我入门学点什么,我都没敢给推荐 C/C++,都只推荐了 python 或者 ruby 之类的,然后可以去学学 Java 。

就我个人感觉而言, C++学习起来慢,正如好多人说的,到处都是学了很久 C++然后只会写黑框框的人,,,对于那些完全没基础的我是不会随便就推荐 C++这种的。如果是有基础的那种,我可能就会考虑一下让他了解了解 C++的。
FrankHB
2016 年 8 月 19 日
@lizon 你的回复有一些比较明显的问题。
1.讲性价比而不顾风险。学茬、低效、一事无成很容易导致性价比一点都发挥不出来。
2.我上面说过不管基本上为了哪种目的学 C ,都有比直接学 C 更有效的策略。
3.你似乎不把 C 当“高级语言”。然而不管 C 的抽象有多不给力,事实上 C 就是彻头彻尾的高级语言。
如果说 C 因为能操作底层实现所以显得低级, C++和 Rust 之流同样也做得到。这和抽象能力的上限没什么关系。
而纯粹的 C ( strictly-conforming ISO C )甚至严格地比 C++更“高级”。比如说, ISO C++引用的 POSIX 的 errno 错误码在 ISO C 里缩水得没剩几个。
可见仅仅要让 C “底层”到堪用到这点程度,就必须学更多 C 以外的东西。更别提二进制互操作了。
注意,你所谓的“俭”——表达相同层次的抽象时对实现细节依赖少——在日常见到的语言中,恰恰就最符合的就是纯粹的 C 。要说其它的,基本上是个日用的语言都不会那么“俭”,而会偷懒假设更多东西。
(当然, C 也不是都不偷懒,比如和 C++一样假定一个字节至少有 8 位,但不管怎么说比 Java 和 POSIX 这样钦定一个字节=8 位总是明显“俭”的。)
C 正是用这点换来了卓越的源码层次的可移植性(尽管实际上由于限制过于严格多数场合并没有什么卵用……)。
所以你说的学 C 只能认为是学 C 和底层的其它知识,这并不比学其它语言+底层知识优越,还更容易引起混乱,同时得到的技能并不实用。
4.混淆抽象性质和实现的层次。
具体来讲,“高级”和“高层”不是一回事,“低级”和“底层”也不是一回事。(有多少人知道有高级汇编语言……?)
底层实现和强调抽象完全不矛盾;相反,为了了解底层实现,一些(和高级语言类似的)抽象是必要的,否则一些情况会导致理解底层这个任务都不具有可行性。
提一下, volatile 本身恰恰就是非常学术的东西,而且算是 designed by committee ( X3J16 )而有正面反馈的典型例子。
工程上实践对 volatile 的大大咧咧反而导致了一大票的误用 bug 的笑话。
比如语言设计领域算是比较著名的 double-checked locking 失败例,最终迫使 Java 更改了 memory model ,而现在 Java 和 C#的 volatile 的意思和 C/C++里的截然不同。
直接根源就是多数用户对 volatile 的想当然。
有多少工程派领会到了这些背景知识?有哪些纯粹的工程需求驱动你去了解这些东西?
我不怎么相信你没有足够的抽象会支持你看得下去,因为具体的东西太细碎了。
另外,像 cache coheretece/memory consistency 这样的东西,我也不信你用反抽象的方式能理解得了。
如果说抽象迟早绕不过去,为什么还要用低效的方法?
5.如果要学院派,请严谨地保持含义的准确。
图灵机与λ演算显然不等价,因为“等价”不等价于“可计算性等价”。
对选择学什么语言入门来讲,恰恰需要在乎其中不等价的部分,比如说抽象能力和性能。
6.注意蕴含逻辑。
即便“ C 的程序更符合初学者的思维方式”,也不自然表示这是初学者需要的思维方式。
何况“ C 的程序更符合初学者的思维方式”其实是很有疑问的。
初学者(乃至有几门其它语言经验的老手)基本上不可能理解 C 的抽象机模型和可观察行为等价的要求,所以没几下子就只能拘泥具体实现了,同时还没搞清楚适用范围。
结果就是一些很重要的基础知识(比如什么是 UB )都缺乏机会掌握,上手做什么就被坑什么,坑了还未必能总结出规律下次避开。
这样还不如直接就来抽象能力强一点的语言呢……好歹能上手把更多的事做对,而不至于找不到方向。
FrankHB
2016 年 8 月 19 日
@lizon 关于反面教材我倒是可以再解释一下。

对于搞语言实现的来讲, C 勉强顶用(但现在也不必要),但对 PLT ,以 C 作为目标是坏榜样。

理由和可计算性没什么关系,而是抽象设计的局促,不仅比起更现代的语言没有优势,功能和设计的一致性上就显著地比同时代的 Lisp 方言劣等。(为什么没有一等函数?)

即便是学习过程中 C 充其量也就是个中间产品,这样还不如直接用 C--或者 LLVM IR 什么的免得什么 decay 之类乱七八糟不务正业扰乱视线。

此外, C 的很多经典的设计,以现在的观点来看,是迁就实现的落后而带有误导性质的设计。这对于几乎所有用户都会产生效果。

比如指针,说穿了就是一堆能共用实现但抽象上本不需要相关的 sum type 。然而先学 C 学岔了不去补习其它语言设计策略或者理论的,基本上就没机会去自己发现 sum type 了,却实实在在“享受”这些设计带来的易错和其它工程上明显低效性质而浑然不自知甚至自以为优越。

(类似指针的东西当然是有用的,但不需要也最好避免在 C 这个层次上提供。)

再如数组的[],一定意义上导致用户对真实的实现上对应的操作具有错误的复杂度假设——尽管严格来说这不算 C 的问题( C 也确实没保证)。
muziki
2016 年 8 月 19 日
@FrankHB 终于把您 V 站上所有的回复看完了……对计算机的理解简直可怕,能斗胆问下您怎么发现研究这些像我这种“半瓶醋”面对某种语言出现的理解错误?(例如你回复里面提到的 C 语言抽象性某种程度上高于 Cpp ,动态静态问题之类的)
SeanLin
2016 年 8 月 19 日
如果你足够新手的话,建议先从你想做的产品来反推改点的技能树。
btw C 上手很好 C++上手很不好
taozhijiangscu
2016 年 8 月 19 日
C 作为入门语言是十分经典的,不然也不会这么多年傻乎乎作为计算机科班和非科班的入门语言了。而且 C 其实很简单也很直白,不像 C++具有很多潜规则。此外现在 C++标准越来越臃肿了,不知道是不是标准协会在刷存在感。
入门之后,基本就是 C++、 Java 分流了,两个语言极其相似,但除了性能、可移植性等因素外,最大的差异就是内存回收的机制了, Java 简单,开发效率高,也不容易写出有大问题的代码,虽然 Java 很不低碳环保。
当然我是说的服务端的开发,其它不了解就不评了。
jeffersonpig
2016 年 8 月 19 日
用了 5 年 C++,表示不会,但是会推荐 C 。 C 认真学习锻炼之后根据自己兴趣和工作需要再去选择其它语言。
jefferyfan
2016 年 8 月 19 日
编程语言的思想是相通的,学完 C/C++之后,其他大部分语言都很快可以上手。 但是上手之后,语言的特性还是需要去学习。
FrankHB
2016 年 8 月 19 日
@muziki 自己了解,不要人云亦云。
比如说……
@taozhijiangscu ←反面教材。
是不是简单直白就不说了,自己比较 spec 去。
只是需要多澄清一点: C 的潜规则一点都不比对应的 C++少,而且往往更膈应人。
int i; int; int main(void){}呵呵……
至于为啥多数人都没法注意嘛……写书卖钱教你的会拿自己都没把握搞清楚的东西来恶心你劝退?
FrankHB
2016 年 8 月 19 日
噫……又抽……
int i; int i; int main(void){}
关键字 tentative definition 。
很讽刺的是只看 ISO C 基本是看不懂为什么需要这玩意儿的。倒是 ISO C++的 Annex C 里讲不兼容 C 的部分时会说清楚理由。
ytjfmv
2016 年 8 月 19 日
@FrankHB 能解释一下 C 的 object 是什么么? 十分感谢
21grams
2016 年 8 月 19 日
c++一样可以做 web ,也有 web framework
ecloud
2016 年 8 月 19 日
@taozhijiangscu C++和 Java 最大的区别是, Java 有一个官方,基本库固定,各种方法特性都很清楚明确。而 C++是多头主义,一家一个风格,一个做了 5 年 MFC 的人去搞 Qt ,会发现“这都是什么鬼?”
ykk
2016 年 8 月 19 日
还是根据需求来 以后想做什么 本科基础大多是开 C 吧 开 C++是基于什么考虑?
kingddc314
2016 年 8 月 19 日
搞 C++的,但是我推荐 Go
ecloud
2016 年 8 月 19 日
@FrankHB 很多东西由于历史久远的误解,以讹传讹,黑的被说成了白的。关于历史问题我曾经在别处说过多次,大概 V2 这里人的年龄都比较小,所以不甚了解。
最初 K&R 他们发明 C 语言的时候就是想要一个“更好用的汇编”,所以他们的 C 编译器写的非常宽松和随意,目的就是为了尽量体现低级语言的特征,然而从 C 本身的语法构成来说,其实就是简化版的 Pascal 。由于 K&R 他们对编译器开了那么一个头,造成了后来的 C 编译器跟着学样,比如早期的 gcc 。所以 C 的所谓“低级语言特性”其实是背了编译器的黑锅。
常年玩 C 的人会发现一个状况,就是你的程序在两台不同的机器上编译的话,有可能会产生不同的结果,而这不同的结果几乎都是由于代码里某个深层次的 Bug 引起的(一般都是内存分配和数组越界问题)。但是如果你一直在一台固定的机器上编译的话,这个 Bug 可能一辈子都不会被发现。然而像 TurboC 这种非 K&R 模式的编译器则完全不会出现这种情况,一段代码在无论哪台的 TC 上编译都是同一个结果,因为 TC 默认使用一个沙盒来编译。

再说说 Pascal 的问题。在 K&R 风格的 C 编译器开始流行的年代, Pascal 的流行用法是先预编译成 p 代码,然后在 UCSD-p 系统上运行的。这跟后来的 Java 很像,换句话说,就是在虚拟机上运行。所以,一个靠虚拟机运行的语言,怎么可能控制底层和内存这些东东呢? Pascal 也背了编译器的黑锅,给人一种不具有底层控制能力的错觉。然而实际上,世界上大部分的飞机导弹的控制程序是 Ada 写的, Ada 不就是穿了件马甲的 Pascal 么!

最后关于 C 的强弱类型问题,是个持续了几十年的论战了。反正在我的概念中, if (a=5) 这种不光能编译通过还能发挥有效的实际作用的语言,都谈不上强类型
Ferouden
2016 年 8 月 19 日
@wangxn 刷题……哥们我们一起去刷 OJ 把?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://v2ex.ih06.com/t/300102

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX