《C++编程调试秘笈》——第1章 C++的缺陷来自哪里

    xiaoxiao2024-03-14  129

    第1章 C++的缺陷来自哪里

    C++编程调试秘笈C++语言是非常独特的。虽然实际上所有的编程语言都从其他语言中吸收了一些思路、语法元素和关键字,C++却是吸收了另一种完整的语言,即C语言。事实上,C++语言的创建者Bjarne Stroustrup原先把他的新语言命名为“带类的C”。这意味着如果我们已经使用了一些C代码,并且由于某种原因(例如科研或贸易)切换到一种面向对象的语言,就不需要在移植代码方面采取任何措施,只要安装新的C++编译器,就可以对旧的C代码进行编译了,并且效果和原先的一模一样。我们甚至会觉得已经完成了从C到C++的转换。最后这种想法虽然距离真相还很远,用真正的C++所编写的代码与C代码看上去存在很明显的区别,但它还是提供了一个逐渐过渡的选项。也就是说,我们可以从现在编译运行的C代码出发,逐渐引入用C++所编写的新代码段,慢慢与它们混合在一起,最终实现到纯C++的切换。因此,C++的层次式设计具有它独特的市场推动力。

    但是,其中还是存在一些复杂的地方:随着C的完整语法被新语言完整地吸收,它的设计哲学和存在的问题也同样被吸收。C语言是在1969年~1973年期间由Dennis Rithie在贝尔实验室创建的,其出发点是为了编写Unix操作系统。这项工作的一个伴随成果是诞生了一种高效的高级编程语言(与需要编写每条计算机指令的汇编语言相比)。也就是说,它所产生的编译后的代码应该具有尽可能快的速度。这种新的C语言的其中一项公开原则是,用户不应该为他没有使用到的特性而受到拖累。因此,为了追求高效的编译代码,对于程序员没有提出明确的要求,C就绝对不会加以考虑。C语言是为了速度而不是为了舒适而创建的,这就产生了一些问题。

    首先,程序员可以创建一个某种长度的数组,并用一个超出该数组边界的索引值访问一个元素。更容易被滥用的是C的指针运算,程序员可以把指针运算所产生的任何值作为内存地址并对它进行访问,不管这块内存是否应该被访问。(实际上,这两个问题其实是同一个,只不过使用了不同的语法。)

    程序员还可以在运行时使用calloc()和malloc()函数动态分配内存,并使用free()函数负责动态内存的销毁。但是,如果忘了销毁或者不小心销毁了多次,其结果可能是灾难性的。

    我们将在本书的第二部分深入讨论这些问题中的每一个。需要重视的是,C++在继承整个C时,除了传承它的高效原则,还继承了它的所有问题。因此,C++代码中的部分缺陷就来源于C。

    但是,故事并没有结束。除了来自于C的问题,C++自身也存在一些问题。例如,大多数人认为友函数和多重继承并不是良好的编程思路。C++具有自己分配内存的方法,它并不是调用像calloc()或malloc()这样的函数,而是使用操作符new。new操作符并不仅仅分配内存,它还创建对象,即调用它们的构造函数。与C的精神相同,使用delete操作符删除动态分配的内存是程序员的责任。现在的情况看起来与C相同:我们分配了一些内存,然后删除它。但是,复杂之处在于C++具有两种不同的new操作符:

    在第一种情况下,new操作符创建了一个MyClass类型的对象。在第二种情况下,它创建了一个相同类型的对象数组。与之对应的是,C++具有两种不同的delete操作符:

    当然,一旦使用了“带方括号的new”创建对象,就需要使用“带方括号的delete”删除它们。这样就可能导致一种新的错误:混用new和delete,其中一个带了方括号而另一个没有带方括号。如果出现了这种错误,就会对内存堆产生巨大的破坏。因此,我们可以总结如下:C++的缺陷大部分来源于C,但C++也引入了一些自讨苦吃的新方法。我们将在本书的第二部分讨论这些话题。

    本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)