c++面试重要考点

第一章 C++基本考点

1.1 命令空间

一个潜在的问题:使用两个已封装好的产品,而它们都含一个名字wanda()函数,当使用wanda()函数时,编译器就不知道指的是哪个版本。命令空间让能够将产品封装叫做名称空间的单元中。这样就可以用命令空间的名称来指出想使用哪个厂商的产品。也就说,命令空间是用来把变量名封装起来。

下面一行代码表明,可以使用std名称空间中定义的名称,而不必使用std::前缀。

 using namespace std;

但是在大型项目中,这样做会有一些潜在的危险。

1.2 程序创建 

C++编译器通常进行以下4个步骤将源代码编译为可执行程序:

(1)预处理器的预处理阶段,替换#开头的内容;

(2)编译器编译阶段,将预处理后的源程序处理成汇编源程序;

(3)汇编器的汇编阶段,将汇编源程序汇编为可重定位的目标二进制程序;

(4)连接器将可重定位的目标程序连接成为可执行的二进制目标程序。

预编译阶段,该阶段预处理器会处理以#开头的命令(如#include,#define,#if等),处理之后的输出文件就完全是个纯C++源文件,不再包含预处理命令,当该处理过程将根据#if,#ifdef,#ifndef,#endif来确定是否需要时行相应的处理。.ii为后缀的文件,是已经预处理过的C++源代码文件,.i为后缀的文件,是已经预处理过的C源代码文件。

编译阶段,编译器使用预处理器的输出文件生成汇编源文件,注意只是汇编源代码,也就是此时的文件还只是文本文件。默认情况下生成的文件后缀为.s。

汇编阶段,使用汇编器将汇编源代码汇编为可重定位的目标程序(relocatable object program),该阶段生成的文件为二进制文件,它的字节码是机器语言指令而不是字符。默认输出文件为源程序名加后缀.o。

链接阶段,将各种目标代码以及库文件(*.lib文件),资源文件(*.rec)进行链接处理最终生成可以执行的*.exe文件。重定位发生于目标代码链接阶段,在链接阶段链接器就会查找符号表。当所有的符号变量都能够找到合法的内存地址时,链接阶段重定位完成。在一个目标文件中,其text区从地址0开始,随后是data区,再后面是bss区。而要运行程序,必须装载到内存中,所以这些区的地址需要在内存中重新安排,也就是重定位。

  symbols

         通常情况下可重定位的目标文件中包含三种类型的symbols(其实也是ELF格式的三种类型):

  • 已经定义的”external” symbols,该符号允许被其他模块调用
  • 未定义的”external” symbols,该符号引用在其他模块中已经定义的符号。
  • 局部符号,在目标文件中内部使用以便方便进行重定位。
  • 例如一个C++源码编译生成的可重定位的目标程序中,每个函数、全局变量、静态变量都会有一个symbol与之对应,这些就是已经定义的symbols。定义在不同文件中symbols就是未定义的symbols。在链接期间,链接器会给每个symbol指定一个地址,并会通过查找同名的已经定义的symbol来解决所有未定义的symbol。根据该symbol是局部或全局、已初始化或未初始化、变量还是常量,链接器会将它们放在可执行的目标程序文件中的不同节(sections)。

relocation

         重定位是指一个过程,该过程将为程序中不同部分指定载入地址并调整程序中的代码和数据以将其映射到指定的地址。与重定位过程紧密相关的有重定位表(relocation tables)和一些包含额外信息的特定的节(sections),例如其中一个section就是.rela.text,该节与重定位可执行目标文件中的.text节有关。深入了解相关问题可以参见ELF文件格式。每一个.o文件都有一个重定位表(relocation table),该表给出了每一个需要被链接器更新的符号symbol,以及该如何更新的信息。

参考网站:http://notes.maxwi.com/2016/06/05/source-to-program/

1.3 类简介

        类是用户定义的一种数据类型,要定义类,需要描述它能够表示什么信息和可对数据执行哪些操作。类之于对象就像类型之于变量,也就是说,类定义描述的是数据格式及其用法,而对象则是根据数据格式规范创建的实体。

        类描述了一种数据类型的全部属性(包括可使用它执行的操作),对象是根据这些描述创建的实体。

1.4 在多函数程序中使用using编译指令

让程序能够访问名称空间std的方法有多种,下面是其中的4种:

  1. 将using namespace std;放在函数定义之前,让文件中所有的函数都能够使用名称空间std中所有的元素。
  2. 将using namespace std;放在特定的函数定义中,让该函数能够使用名称空间std中的所有元素。
  3. 在特定的函数中使用类似using std::cout;这样的编译指令,而不是using namespace std;让该函数能使用指定的元素,如cout。
  4. 完全不使用编译指令using,而在需要使用名称空间std中的元素时,使用前缀std::,如下所示:

1.5 类型字节数

         在不同操作系统,不同编译环境下,C++中变量的类型所占的字节数也不相同。下面是在windows 7 64操作系统环境,编译器使用的是DEV-C++5.11。因为64位操作系统,故指针所占4个字节。

1.6 C++中结构体与类的区别

         首先类是C++中面向对象独有的,但是C和C++中都有结构体,下面我们来看一下C和C++中结构体的区别,这里主要从封装、多态、继承、封装和访问权限几个方面来说。

首先,先介绍C和C++中结构体区别。

(1)多态,C的结构体内不允许有函数存在,但是有默认的构造函数,就是把所有的成员属性设置为0,不能自定义。但是C的结构体是没有构造函数、析构函数     、this指针的,所有没有多态而言;C++允许有内部成员函数,且允许该函数是虚函数,可以多态。

(2)继承,C语言的结构体是不可以继承的,C++的结构体是可以从其他的结构体或者类继承过来的,和类一样,实现了代码的复用。

(3)封装,C的结构体只是把数据变量给封装起来了,并不涉及算法,是一种“复合类型”,其功能基本与int、double的用法相同,它主要解决多类型问题。而C++中把数据变量及对这些数据变量的相关算法给封装起来,并且给对这些数据和类不同的访问权限。

(4)访问权限,C的结构体对内部成员变量的访问权限只能是public,而C++允许pubilc、protected、private三种。

以上是四点都是表面的区别,实际区别就是面向过程和面向对象编程思路的区别。

         C++的结构体和C++类的区别,主要是访问权限的区别:

(1) C++结构体内部成员变量及成员函数默认的访问级别是public,而C++类的内部成员变量及成员函数的默认访问级别是private。

(2)C++结构体的继承默认是public,而C++类的继承默认是private。

1.7 共用体和枚举

         共用体(union)是一种数据格式,它能够表示不同数据类型,但只能同时存储其中的一种类型。

         共用体的用途之一是,当数据项使用两种或更多种格式(但不会同时使用)时,可以节省空间。

         C++中enum工具提供了另一种创建符号常量的方式,这种方式可以替代const,

枚举指定的值必须是整数,也可以只显示地定义其中一些枚举量的值,默认从0开始,后面依次加一

 

这里,first在默认情况下为0,后面没有被初始化的枚举量的值将比起前面的枚举量大1,因此,third的值为101,最后,可以创建多个值相同的枚举量。

1.8 指针和引用和数组

1、指针和引用

        指针和引用都是间接引用其他对象。但是引用不能指向空值的引用,也就说,引用必须要初始化,但是指针可以指向空的,但是这样做很危险,很容易出现野指针。引用指向初始化时的对象后,就不能改变了,但是指针可以再指向其他的对象。

        不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高,毕竟不要验证是否是空指针。

        如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么就应该使用引用。

2、数组和指针
       数组一般在栈区开辟空间,也可以在静态区开辟空间(全局数组、静态数组),空间的开辟与回收都由编译器或操作系统来完成,不需要程序员手动执行,不会产生内存泄露。

       指针首先是一个变量,是变量就要有存储空间,所以指针变量一般在栈区存储,如果说指针变量指向一个已存在的变量,则不需开辟空间;如果说指针指向一块动态开辟的空间,需要使用malloc或new开辟,指针变量的值保存的是在堆上开辟空间的首地址,不再使用指针时,需使用free或delete手动释放内存,否则会造成内存泄露。

注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。

1.9 指针

计算机程序在存储数据时必须跟踪的3中基本属性。

  1. 信息存储在何处;
  2. 存储的值为多少;
  3. 存储的信息是什么类型。

        面向对象编程与传统的过程性编程区别在于,OOP强调的是运行阶段(而不是编译阶段)进行决策,运行阶段指的是程序正在运行时,编译阶段指的是编译器将程序组合起来时。C++采用的方法是,使用关键字new请求正确数量的内存以及使用指针来跟踪新分配的内存的位置。

        指针的危险,极其重要的一点是:C++中创建指针时,计算机将分配用来存储数据地址的内存,但不会分配用来存储指针所指向的数据的内存。

        fellow确实是一个指针,但它指向哪里呢?上述代码没有将地址地址赋给fellow,那么223323将被放在哪里呢?我们不知道,由于fellow没有被初始化,它可能有任何值,不管值是什么,程序都将它解释为存储223323地址,如果fellow的值碰巧为1200,计算机将把数据放在地址1200上,即使这恰巧是程序代码的地址,fellow指向的地方很可能不是所要存储223323的地方,这种错误可能会导致一些最隐匿、最难以跟踪的bug。

         一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址。这是关于使用指针的金科玉律。

        要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型:

1.10 指针数组和数组指针

        指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每一个元素都是一个指针,在32位操作系统的指针永远是占4个字节,它是“存储指针的数组”的简称。Int *ptr[10]。

         数组指针:首先它是一个指针,它指向一个数组,在32位系统下任何类型的指针永远是占4个字节,至于它指向的数组占多少字节,不知道,具体要看数组大小,它是“指向数组的指针”的简称。Int (*ptr)[10]。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值