第一章 《C++中的C》

目录

1.什么是强类型定义语言?什么是弱类型定义语言?二者有什么区别?

2.什么是动态类型语言?什么是静态类型语言?二者有什么区别?

3.什么是类型安全?

4.C++和C有什么不同?

5.总结const的应用和作用。

6.volatile关键字的作用是什么?

7.一个指针可以是volatile吗?

8.给出几个使用volatile关键字的示例。

9.说明C++中static_cast和dynamic_cast在使用上的不同

10.C++内存组织结构是什么样的?

11.在C++中支持malloc/free,为什么还需要new/delete?

12.说明new、delete、malloc、free之间的关系。

13.说明delete和delete[]的区别。

14.将引用作为函数参数有哪些特点?

15.C++的引用和C的指针有什么区别?

16.常引用有什么作用?

17.简要说明函数重载。

18.说明assert()的作用。

19.在C++程序中调用被C编译器编译后的函数为什么要加extern "C"?


1.什么是强类型定义语言?什么是弱类型定义语言?二者有什么区别?

强类型语言

强类型语言也称为强类型定义语言,是一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用。

Java、.Net和C++等一些语言都是强制类型定义的,也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。

例如你有一个整数,如果不显式地进行转换,你不能将其视为一个字符串。

弱类型语言

弱类型语言也称为弱类型定义语言,与强类型定义相反。像VB,PHP等一些语言就属于弱类型语言。

简单理解就是一种变量类型可以被忽略的语言。比如VBScript是弱类型定义的,在VBScript中就可以将字符串'12'和整数3进行连接得到字符串'123',然后可以把它看成整数123,而不用显示转换。但其实他们的类型没有改变,VB只是在判断出一个表达式含有不同类型的变量之后,自动在这些变量前加了一个clong()或(int)()这样的转换函数而已。能做到这一点其实是归功于VB的编译器的智能化而已,这并非是VB语言本身的长处或短处。

强类型语言和弱类型语言比较

强类型语言在速度上可能略逊色于弱类型语言,但是强类型语言带来的严谨性可以有效地帮助避免许多错误。

参考:强类型语言、弱类型语言


2.什么是动态类型语言?什么是静态类型语言?二者有什么区别?

动态类型语言

动态类型语言是指在运行期间才去做数据类型检查的语言。也就是说,在用动态类型的语言编程时,永远不用给任何变量指定数据类型,该语言会在你第一次赋值给变量的时候,在内部将数据类型记录下来。Python和Ruby就是一种典型的动态类型语言,其它的各种脚本语言如VBScript也多少属于动态类型语言。

静态类型语言

静态类型语言与动态类型语言刚好相反,它的数据类型是在编译期间检查的。也就是说,在编写程序的时候就要声明所有变量的数据类型。C/C++是静态类型语言的典型代表,其它的静态类型语言还有C#、Java等。

参考:动态类型语言、静态类型语言


3.什么是类型安全?

类型安全简单来说就是访问可以被授权访问的内存位置类型安全的代码不会试图访问自己未被授权的内存区域。一方面,类型安全被用来形容编程语言,主要根据这门编程语言是否提供类型安全的保障机制;另一方面,类型安全也可以用来形容程序,根据这个程序是否隐含类型错误。类型安全的语言和程序之间,其实没有必然的联系。类型安全的语言,使用不当,也可能写出来类型不安全的程序;类型不安全的语言,使用得当,也可以写出非常安全的程序。

C的类型安全

C语言不是类型安全的语言,原因如下:

1)很多情况下,会存在类型隐式转换,比如bool自动转成int类型;

2)malloc函数返回的是void *的空类型指针,通常需要这样的显示类型转换char* pStr=(char*)malloc(100*sizeof(char)),类型匹配没有问题。但如果出现int* pInt=(int*)malloc(100*sizeof(char))这样的转换,可能会带来一些问题,但C并不会提示。

当然,在有些情况下表现还是类型安全的,当从一个结构体指针转换成另一个结构体指针时,编译器会报错,除非显式转换。

C++的类型安全

C++也不是类型安全的语言,但远比C更具类型安全。相比于C,提供了一些安全保障机制

1)用操作符new来申请内存,严格与对象类型匹配,而malloc是void *;

2)函数参数为void *的可以改写成模板,模板支持运行时检查参数类型

3)使用const代替define来定义常量,具有类型、作用域,而不是简单的文本替换;

4)使用inline代替define来定义函数,结合函数的重载,在类型安全的前提下可以支持多种类型,如果改写成模板,会更安全;

5)提供dynamic_cast使得转换过程更安全。

尽管如此,但如果使用空类型指针或者在两个不同类型指针间做强制转换,很可能引发类型不安全的问题。

参考:类型安全


4.C++和C有什么不同?

就语言本身而言,C是C++的一个子集,C++在C的基础上增加了类和模板类型。一方面C++加强了C的过程化功能,引入了重载、异常处理等,另一方面更是扩展了面向对象设计的内容,如类、友元、继承、虚函数和模板等。

从编程角度,C是一种结构化编程语言,重点在于算法和数据结构,C程序设计首要考虑的是如何通过一个过程(包含函数和参数等)对输入进行运算处理得到输出;

而C++是面向对象的编程语言,C++程序设计首要考虑的是如何构造一个对象模型,包括数据封装、类、消息、对象接口和继承等,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程控制,所以两者的区别在于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“设计”这个概念已经被融入C++之中。


5.总结const的应用和作用。

      1.若要阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后没有机会再去改变它了。
      2.对指针来说,可以指定指针本身为const,也可以指定所指的数据为const,或二者同时指定为const
      3.在一个函数定义中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值
      4.对于类的成员函数,若指定其为const类型,则表明其是一个常成员函数,不能修改类的数据成员
      5.对于类的成员函数,有时必须指定其返回值为const类型,以使得其返回值不为”左值”


6.volatile关键字的作用是什么?

volatile关键字的含义是“易变的”,它告诉编译器volatile变量是随时可能发生变化的,与volatile变量有关的运算不要进行编译优化,以免出错,因为一般的编译器会进行编译优化。

用volatile关键字修饰的变量确保编译器不对其代码进行优化,且要求每次直接从内存读值。


7.一个指针可以是volatile吗?

可以,因为指针和普通变量一样,有时也可能会被意想不到地改变。例如,中断服务子程序修改一个指向buffer的指针时需要用volatile来修饰这个指针。


8.给出几个使用volatile关键字的示例。

一个定义为volatile的变量就是说它可能会意想不到的改变(改变它的情况有很多,例如操作系统,硬件,线程),在用到这个变量时必须每次都小心地从内存总读取这个变量的值,而不是使用保存在cache或者寄存器里的备份。

Volatile修饰符告诉编译程序不要对该变量所参与的操作进行优化。

例子:

1)  并行设备的硬件寄存器,如状态寄存器

2)  一个中断服务子程序中会访问到的非自动变量。

3)  多线程应用中被几个任务共享的变量。


9.说明C++中static_cast和dynamic_cast在使用上的不同

static_cast用于明确定义的转换,包括编译器允许不用强制转换的“安全”转换和不太安全但清楚定义的转换,如窄化转换(可能有信息丢失)、使用void *的强制转换和隐式类型转换等。dynamic_cast适用于类型安全的向下转换,常用在继承中的父类指针向子类指针的转换。若转换成功则返回该类型的指针,若失败则返回NULL。

参考:C++中static_cast和dynamic_cast


10.C++内存组织结构是什么样的?

代码段:用来存放程序的执行代码。通常代码段是可共享的和只读的,以防止程序被意外修改。

数据段:包含BSS段和静态数据区两个部分。BSS段用来存放程序中未初始化的外部变量和未初始化的静态局部变量(执行开始程序前BSS段会预先清空)。静态数据区用来存放程序中已初始化的外部变量、静态局部变量和常量。

堆空间:用于存放程序执行中动态分配的内存段,它的大小并不固定,可动态扩张或缩减。一般来讲在32位系统中堆内存可以达到4GB的空间。堆空间中存放的对象是全局的。

栈空间:存放程序中临时创建的局部变量(但不包括static定义的静态变量)、函数参数和函数返回地址等。一般情况下,栈空间有一定的大小,通常远小于堆空间。栈空间中存放的对象是局部的。


11.在C++中支持malloc/free,为什么还需要new/delete?

malloc/free是c/c++语言的标准库函数,new/delete是c++中的运算符。它们都用于申请动态内存和释放内存。

对于非内置数据类型的对象而言(eg:类对象),只用malloc/free无法满足动态对象分配空间的要求。这是因为对象在创建的同时需要自动执行构造函数,对象在消亡之前要自动执行析构函数,由于malloc/free是库函数而不是运算符,不在编译器的控制权限内,不能将执行构造函数和析构函数的任务强加给malloc/free。所以,在c++中需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理和释放内存工作的运算符delete。

对于内置数据类型而言,malloc/free和new/delete的作用是等价的。既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用纯C函数,而纯C程序只能用malloc/free管理动态内存。


12.说明new、delete、malloc、free之间的关系。

new/delete是运算符,malloc是库函数。

malloc和new都用于分配内存空间,但new会调用对象的构造函数,而malloc不会。free和delete都用于释放内存空间,但delete会调用对象的析构函数,而free不会。

如果用free释放new创建的动态对象,那么该对象因无法执行析构函数而可能导致程序出错;如果用delete释放malloc申请的动态内存,尽管不会导致程序出错,但是这样的程序可读性很差,所以,new/delete必须配对使用,malloc/free也一样。


13.说明delete和delete[]的区别。

delete运算符只会调用一次析构函数,而delete[]表达式会调用每一个成员的析构函数。例如,当delete[]运算符用于数组时,它为每个数据元素调用析构函数,然后调用delete释放内存。delete与new配套使用,delete[]与new[]配套使用。


14.将引用作为函数参数有哪些特点?

调用函数时实参和对应的引用形参共享相同的存储空间,所以在执行函数时引用型形参的改变和实参是同步的,也就是说对被调用函数中引用型形参的操作就是对实参的操作。尽管通过传递指针的方式可以达到改变实参的目的,但采用引用参数不仅简单,而且程序更清晰、可读性更好。

在调用函数时,在内存中并没有为实参对应的引用形参创建实参的副本,它是直接对实参操作,而使用一般变量传递函数的参数,当调用函数时需要为对应形参分配存储空间,形参变量是实参变量的副本,如果传递的是对象,还将调用拷贝构造函数,因此当参数传递的数据较大时用引用比用一般变量传递参数的效率要好,所占的空间要少。


15.C++的引用和C的指针有什么区别?

引用必须被初始化,但是不分配存储空间。指针在定义时不一定初始化,定义指针需要分配相应的存储空间。

引用初始化以后不能被改变,指针可以改变所指的对象。

不存在引用空值的引用,但存在指向空值的指针。


16.常引用有什么作用?

常引用主要是为了避免使用变量的引用时在不知情的情况下改变参数的值。常引用主要用于定义一个普通变量的只读属性的别名,作为函数的传入形参,避免实参在调用函数中被意外地改变。


17.简要说明函数重载。

在同一个作用域内(如在同一个类中),可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。


18.说明assert()的作用。

assert()是一个调试程序时经常使用的宏,在程序执行时它计算括号内的表达式,如果表达式为假,程序将报告错误,并终止执行;如果表达式为真,则继续执行后面的语句。这个宏通常用来判断程序中是否出现了明显非法的数据,如果出现了则终止程序以免导致严重后果,同时也便于查找错误。


19.在C++程序中调用被C编译器编译后的函数为什么要加extern "C"?

C++支持函数重载,C不支持函数重载。函数被C++编译后在库中的名字与C语言不同。假设某个函数的原型为void foo(int x,int y),则该函数被C编译器编译后在库中的名称为_foo,而C++编译器会产生像_foo_int_int之类的名称。C++提供了C链接指示符extern "C"来解决名称匹配问题。


参考:《直击招聘 程序员面试笔试 C++语言深度解析》李春葆、李筱池 主编

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值