概述:学习和使用过C++的人几乎都曾经听说过下面的五个关于C++的观点,并且对这些话笃信不已,那么真实的情况是怎么样的呢?本文的作者——C++之父Bjarne Stroustrup将会对这些观点作逐一回击。
以下的这五个观点盛行于C++多年:
- “要了解C++,你必须先学习C语言。”
- “C++是一门面向对象的语言。”
- “对于可靠的软件,垃圾回收机制必不可少。”
- “为了提高效率,你必须编写底层代码。”
- “C++只对大型复杂的项目有用。”
如果你还对这些观点深信不已,那么这篇文章可以给你一些重新认识。这些观点在特定的时间对于某些人、某些工作来说是正确的。但是对于今天的C++,随着ISO C++11标准的编译器和工具的广泛使用,这些观点都需要被重新认识。
- C++之父谈关于C++的五个需要被重新认识的观点(上)
- C++之父谈关于C++的五个需要被重新认识的观点(中)
接下来,我们将会对这些观点进行逐一反驳。
观点一:“要了解C++,你必须先学习C语言。”
这不对,事实上对于基础编程的学习来说C++比C语言容易的多。
C语言虽然几乎可以认为是C++的子集,但对初学者来说却不是最容易学习的。因为C语言缺乏标记支持和类型安全,并且对于简化简单任务来说C++的标准库更加易于使用。
比如,对于一个非常简单的用于描述邮件地址格式的函数:

它可以被这样使用:

而C语言中需要明确的字符操作和明确的内存管理:

然后,它需要被这样使用:

相比之下,哪种版本更加容易学习?哪种语言更加有效率?很显然是C++了,因为它不需要计算参数字符,不需要为简短的字符串分配动态内存。
关于“C语言优先学习”的观点并非来自少部分人的认识。传授这种典型观点的老师主要有以下几个方面原因:
- 因为这是他们在这方面有丰富经验。
- 因为这是课程需求。
- 因为这是老师年轻时的学习方式。
- 因为C比C++要小,所以更容易学习。
- 因为学生迟早都必须学习C语言或者C++的C语言子集。
然而,C语言并不是作为优先学习的最简单和有用的C++子集。当你知道足够多的C++知识后学习C语言则会非常容易。这种学习方式可以有效减轻从C到C++学习时在认识和技术上的困难。
对于现代C++的教学方法,可以参见我的著作:Programming: Principles and Practice Using C++。它甚至在有一章的结尾处展示了如何学习使用C语言。这种教学方法在几所大学的数以万计学生中使用,非常的成功。它的第二版是使用C++11和 C++14来让学习变得更加容易。
C++11标准使C++更容易被初学者接受,例如,这里是一个元素序列已初始化的vector标准库:

在C++98中,我们只能初始化数组和列表。在C++11中,我们可以定义一个包含有{}和需要的任何类型的初始化列表的构造函数。
我们可以通过for循环的范围来遍历vector:

对于v的任何一个元素都会调用一次test()。
for循环的范围可以遍历任何序列,因此我们可以通过直接使用初始化列表来简化示例。

C++11的目的是使简单的事情变得简单。代码的简单化并没有以性能降低为代价。
观点二:“C++是一门面向对象的语言。”
不对。C++支持面向对象和其它编程风格,它并不仅限于“面向对象”这个狭隘的观点。它支持一个综合的编程技术,包括面向对象和泛型编程。通常一个问题的最佳方式需要比较多种类型。最佳,在这里指的是时间最短、最易于理解、最有效率和最易于维护等等。
“C++是一门面向对象的语言”的观点使人们在除非需要拥有许多虚拟(多态运行)函数的巨大类层次结构时才会考虑使用它。而这种用法对于许多问题来说是不合适的。这个观点也会导致另外一些人指责C++的面向对象并不纯粹。毕竟,如果把“好”和“面向对象”划上等号的话,C++还包含了其它被认为是“不好”的非面向对象的东西。这种观点产生的两种认识都会导致人们放弃学习C++。(译者注:作者表达的意思就是把C++比作是一个卖包子和卖米线的餐馆。将C++认作是包子铺会让人产生2种误会,其一,路过的人会以为这里只卖包子,不卖其它的;其二,爱吃包子的人会认为包子铺还卖米线,这包子一定做得不专业)
举个例子:

它面向对象吗?当然,它严重依赖包含虚函数的类层次结构。它是泛型编程吗?当然是,它严重依赖于参数化容器(vector)和泛型函数for_each。它是函数式编程吗?在一定程度上是,它使用了匿名函数(由[]构造)。那么它到底是什么?它是现代C++:C++11。
我同时使用了for循环和标准库算法for_each只是为了展示其特性。在实际代码中,我只会使用其中的一个循环。
你想让上面那段代码更通用吗?因为毕竟它只适用于vector指针的Shape基类。那么对于列表和内置数组呢?对于象shared_ptr和unique_ptr这样的“智能指针”(资源管理指针)呢?对于没有调用Shape类的对象能够使用draw()和rotate()么?可以这样来做:

你可以使用这段程序对任何序列从头到尾进行遍历。这是一个C++风格的标准库算法。我使用了auto来避免必须为“象Shape类这样的对象”的接口类型命名。这是C++11的特性,它的含义是“使用被用于初始化的表达式的类型”。所以由for循环中p的类型就能决定这是什么类型的对象。这种使用auto表示匿名函数参数类型的方法是现已广泛使用的一个C++14新特性。
如下图所示:

在这里我假定Blob是包含了操作函数draw()和rotate()的图形化类型,而Container是容器类型。标准库list(std::list)拥有成员函数begin()和end(),用于帮助用户遍历元素的序列。这是很好很经典的面向对象编程。但是,假如容器不支持C++标准关于遍历半开序列[b:e)的概念呢?假如库里面没有begin()和end()成员函数呢?或者,由于没有容器一类的东西因此无法遍历。对于这些情况,我们可以用适当的语义来定义独立的begin()和end()。标准库提供了C语言风格的数组,因此如果容器是C语言风格的数组,问题就迎刃而解了——而C语言风格的数组非常常见。
来看看一个更难点的例子,假如容器保留了对象的指针,并且有一个用于访问和遍历的不同模型呢?比如,你会访问到象下面的这个容器:

这种风格并不少见,我们可以将其映射到[b,e)这样的一个序列:

注意,这种修改是无关紧要的:我并没有修改容器或者某些由C++标准库支持的将容器映射到模型进行遍历的容器类的层次结构。这是改写的一种形式而不是重构。
我选择这个例子是为了说明这些泛型编程技术并不局限于流行的标准库。它们也符合常见的“面向对象”的定义,但是它们却不是面向对象的。
关于C++的代码一定是面向对象(意味着在每个地方都会使用层次结构和虚函数)的观点深深地影响了人们对C++性能的评价。还有一些人认为当需要解决多种类型的运行的问题只有面向对象才是最好的。在以前,我也是这么想的。但是事实上,它也有死板的一面(比如并不是所有相关类型都属于同一层次结构)并且虚函数无法作为内联函数(这就使得处理许多简单而重要的任务时会多花费大量的时间)。
下一篇将会围绕“对于可靠的软件,垃圾回收机制必不可少。”的观点进行说明……
本文翻译自Five Popular Myths about C++, Part 1,作者为:C++之父Bjarne Stroustrup
相关推荐
《C++之父Bjarne谈C++的未来发展》一文深入探讨了C++语言及其标准库的发展方向,尤其关注于解决现有标准中的一些缺陷,以及如何更好地支持泛型编程和初学者。以下是对该文章核心观点的详细解析: ### 泛型编程的...
Linux 之父 Linus Torvalds 对 C++ 的炮轰和 Dmitri Kakurin 的回应 Linux 之父 Linus Torvalds 在最近的一篇文章中炮轰 C++,称其为糟糕的语言,认为它会导致非常糟糕的设计选择和低效的抽象编程模型。Torvalds ...
- **解释**:这两本书分别由C++之父Bjarne Stroustrup和Scott Meyers撰写,是学习C++不可多得的资源。它们不仅涵盖了语言的基础部分,还深入讲解了高级主题和内部实现机制。 - **建议**:虽然这些书籍可能比较晦涩...
之道 》,其中很多观点我看了很受启发,以前我也将"设计模式" 看成一个简单的解决方案,没有从一种高度来看待"设计模式"在软 件中地位,下面是我自己的一些想法: 建筑和软件某些地方是可以来比喻的 特别是中国传统建筑...
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
2025年自动化仪表创业项目方案.docx
cmd-bat-批处理-脚本-Messagebox_Cancel_TryAgain_Ignore.zip
cmd-bat-批处理-脚本-GenerateUnionWinMD.zip
cmd-bat-批处理-脚本-shift.zip
电力系统潮流计算是电力工程领域的一项核心技术,主要用于分析电力网络在稳态运行条件下的电压、电流、功率分布等运行状态。MATLAB凭借其强大的数值计算功能和便捷的编程环境,成为电力系统潮流计算的重要工具,它提供了丰富的数学函数库,能够高效地处理复杂的电力系统计算任务。 本压缩包中的“潮流计算MATLAB程序”是一套完整的电力系统潮流计算解决方案,主要包括以下几个关键部分: 数据输入模块:该模块负责读取电力系统的网络数据,包括发电机、线路、变压器等设备的参数。这些数据通常来源于IEEE测试系统或实际电网,并以特定格式存储。 网络建模:基于输入数据,程序构建电力系统的数学模型,主要涉及节点功率平衡方程的建立。每个节点的注入功率等于其消耗功率,对于发电机节点还需考虑其有功和无功功率的调节能力。 迭代算法:潮流计算的核心是求解非线性方程组,常见的算法有牛顿-拉夫森法和高斯-塞德尔法。MATLAB的优化工具箱可辅助实现这些算法,通过迭代更新节点电压和支路电流,直至满足收敛条件。 结果输出:计算完成后,程序能够输出关键性能指标,如节点电压幅值和相角、支路功率流、发电机的有功无功功率等。这些信息对于分析电网运行状态和制定调度策略具有重要意义。 可视化功能:程序可能包含图形用户界面(GUI),用于展示计算结果,例如绘制网络拓扑图并标注节点电压和支路功率,便于用户直观理解计算结果。 错误处理与调试:良好的程序设计应包含错误检测和处理机制,以应对不合理数据或计算过程中出现的问题,并给出适当的提示。 对于电力系统分析课程的学生来说,这个MATLAB程序是一个宝贵的学习资源。它不仅有助于学生掌握电力系统的理论知识,还能让他们了解如何将理论应用于实践,通过MATLAB解决实际问题。尽管该程序是作者一周内完成的,可能存在一些未完善之处,但使用者可以在参考的基础上逐步改进和完善,使其更贴合自身需求。 总之
cmd-bat-批处理-脚本-updaterjs.zip
cmd-bat-批处理-脚本-fsharp.zip
内容概要:该论文深入研究了双馈感应发电机(DFIG)的频率耦合特性及其对系统稳定性的影响。传统阻抗分析方法将DFIG系统解耦为正序和负序子系统进行分析,但当系统中存在频率耦合时,这种线性假设可能导致错误的稳定性结论。论文重点分析了由PLL(锁相环)和不对称转子电流控制引起的频率耦合现象,建立了描述DFIG频率耦合特性的解析模型,并通过仿真验证了模型的有效性。基于该模型,论文进一步分析了系统稳定性及频率耦合的影响因素,表明阻抗分析方法相比传统特征值分析方法更具优势,即使无法建立解析模型,也可通过实验或仿真获得阻抗模型。此外,论文提供了详细的Python代码实现,包括DFIG参数定义、阻抗模型构建、稳定性分析及可视化结果。 适合人群:电力系统工程师、风电系统研究人员、高校电气工程专业师生等具有电力系统基础知识和一定编程能力的专业人士。 使用场景及目标:①用于理解和研究DFIG系统在风电场中的频率耦合特性;②帮助工程师和研究人员分析DFIG系统的稳定性,识别潜在的次同步振荡风险;③为实际风电系统的稳定性评估和优化提供理论依据和技术支持。 其他说明:该论文不仅提供了理论分析,还通过Python代码实现了完整的DFIG频率耦合建模和稳定性分析流程。
2025年职称计算机考试理论模拟试题及答案.docx
《全统计:CMU课程1-10章课后答案详解》是一份极具价值的学习资料,专为卡内基梅隆大学(CMU)“全统计”课程的前10章课后习题提供详尽的解题指导。该压缩包内含10个PDF文件,每个文件对应一章的详细解答,目的是助力学生深刻领会统计学的基础知识、核心理论与实际应用。 在第一章中,通常会讲解统计学的基本概念,例如样本与总体、参数估计、概率分布等。答案详解会涵盖如何计算平均值、中位数、众数,以及如何分析这些统计量之间的差异。同时,还会介绍随机变量和概率分布,如二项分布、正态分布等内容。 第二章主要涉及抽样分布理论,包括中心极限定理,这是统计推断的关键基础。答案详解会说明如何借助抽样分布开展假设检验,例如t检验和z检验。 第三章则深入探讨置信区间的构建以及假设检验的方法。答案详解会详细阐述如何确定置信水平,以及在不同情境下如何选择单尾或双尾检验。 第四章通常聚焦于线性回归模型,包括回归方程的建立、残差分析以及多重共线性问题。答案详解会展示如何解读回归系数,预测未知变量,并解释相关性的强度和方向。 第五章可能探讨非参数统计方法,这些方法不依赖于特定的分布假设,例如Kolmogorov-Smirnov检验、Mann-Whitney U检验等。答案详解会解释在数据分布未知时如何开展统计分析。 第六章将涉及单因素和多因素方差分析(ANOVA),用于比较不同组间的均值差异。答案详解会详细说明如何执行ANOVA,解释F统计量及其意义。 第七章可能涵盖实验设计的基本原则,包括随机化、复制和控制。答案详解会说明如何设计有效的实验以减少偏差,以及如何分析实验结果。 第八章可能涉及时间序列数据的特性,如趋势、季节性和周期性。答案详解会介绍ARIMA模型、自回归移动平均模型等,并解释如何预测未来趋势。 第九章可能深入到多元统计领域,包括多元线性回归、主成分分析、因子分析等。答案详解会介绍如何处理多维
提供一份MATLAB代码,采用Fox-Li迭代算法,只需复制粘贴到MATLAB软件中即可直接运行,非常便捷且精准。
cmd-bat-批处理-脚本-register_python.zip
cmd-bat-批处理-脚本-GetOSVersion.zip
基于GAN的视景图像超分辨率重 建方法研究.zip
极化码(Polar Code)是由土耳其科学家Erdal Arıkan在2009年提出的一种新型纠错编码技术。它通过利用信道的极化现象,将虚拟信道分为误码率接近0和接近1/2的两类。在编码设计中,数据被放置在误码率极低的信道上,从而实现高效的数据传输。极化码的主要优势在于其理论编码容量能够达到香农限,并且构造方法较为简单。 MATLAB是一种功能强大的数学计算和编程工具,广泛应用于科学研究和工程领域。在极化码的研究中,MATLAB可用于构建编码和解码算法,模拟数据在不同信道条件下的传输效果,验证理论性能,并优化相关参数。 SC(Successive Cancellation,逐位取消)译码是极化码的基本解码方法。它从最可靠的比特开始,依次解码每个虚拟信道,且每个比特的解码结果会影响后续比特的解码,因为它们之间存在依赖关系。虽然SC译码的实现较为简单,但其计算复杂度较高,随着码长的增加,解码时间会线性增长。 SCL(Successive Cancellation List,逐位取消列表)译码是SC译码的改进版本。它通过引入列表机制,同时处理多个路径,从而增强了错误校正能力,并在一定程度上降低了错误率。与SC译码相比,SCL译码虽然需要消耗更多的计算资源,但能够提供更好的性能。 一个完整的MATLAB仿真资源通常包含以下内容: 编码模块:用于实现极化码的生成,包括码字构造和极化矩阵操作等。 信道模型:用于模拟各种通信信道,例如AWGN(加性高斯白噪声)信道或衰落信道。 SC/SCL译码模块:包含SC译码和SCL译码的算法实现。 误码率(BER)计算:通过比较发送和接收的码字,计算误码率,以评估编码性能。 性能曲线绘制:绘制误码率与信噪比(SNR)之间的关系曲线,展示不同译码策略的性能差异。 使用说明:指导用户如何运行仿真,理解代码结构,以及如何调整参数以进行自定义实验。 代码注