C++面试题集锦.pdf

所需积分/C币:49 2019-11-11 14:38:50 2.93MB PDF
142
收藏 收藏
举报

C++面试经验总结,已经拿了好几个大厂offer. 内容包含C++的基础知识,引用和指针的区别 以及操作系统,网络,linux等计算机基础知识
4.形参与实参的区别? 1)形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存 单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使 用该形参变量。 2)实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数 调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋 值,输入等办法使实参获得确定值,会产生一个临时变量。 3)实参和形参在数量上,类型上,顺序上应严格一致,否则会发生“类型不匹配”的 错误。 4)函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形 参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中 的值不会变化 5)当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们 在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候 形参被释放,而实参内容不会改变 1)值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象 或是大的结构体对象,将耗费一定的时间和空间。(传值) 2)指针传递:同样有一个形参向函数所属的栈拷贝数据的过程,但拷贝的数据是一个 固定为4字节的地址。(传值,传递的是地址值 3)引用传递:同样有上述的数据拷贝过程,但其是针对地址的,相当于为该数据所在 的地址起了一个别名。(传地址) 4)效率上讲,指针传递和引用传递比值传递效率高。一般主张使用引用传递,代码逻 辑上更加紧凑、消晰 5. statIc的用法和作用? 1.先米介绍它的第一条也是最重要的一条:隐藏。( static函数, static变量均可) 当同时编译多个文件时,所有未加 static前缀的全局变量和函数都具有全局可见性 2. static的第二个作用是保持变量内容的持久。( static变量中的记忆功能和全局生 存期)存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的 次初始化。共有两种变量存储在静态存储区:全局变量和 static变量,只不过和全局 变量比起来, static可以控制变量的可见范围,说到底 static还是用来隐藏的。 3. static的第三个作用是默认初始化为0( static变量) 其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区, 内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量 4. static的第四个作用:C++中的类成员声明 static 1)函数体内 static变量的作用范围为该函数体,不同于auto变量,该变量的内存 只被分配一次,因此其值在下次调用时仍维持上次的值; 2)在模內的 static全局变量可以被模块內所用函数访问,但不能被模块外其它函 数访问; 3)在模块内的 static函数只可被这一模块内的其它函数调用,这个凶数的使用范围 被限制在声明它的模块内; 4)在类中的 static成员变量属于整个类所拥有,对类的所有对象只有一份拷 贝 5)在类中的 static成员函数属于整个类所拥有,这个函数不接收this指针,因而 只能访问类的 static成员变量 类内 6) static类对象必须要在类外进行初始化, static修饰的变量先于对象存在,所以 static修饰的变量要在类外初始化 7)由」 static修饰的类成员属」类,不属于对象,因此 static类成员凼数是没有t his指针的,this指针是指向本对象的指针。正因为没有this指针,所以 static 类成员函数不能访问非 static的类成员,只能访问 static修饰的类成员 8) static成员函数不能被 virtual修饰, static成员不属于仟何对象或实例,所以 加上 virtual没有任何实际意义;静态成员函数没有this指针,虚函数的实现是 为每一个对象分配一个vptr指针,而vptr是通过this指针调用的,所以不能为 virtual;虚函数的调用关系,this->vptr-> ctable> virtual function 6.静态变量什么时候初始化 1)初始化只有一次,但是可以多次赋值,在主程序之前,编译器已经为其分配好了內 2)静态局部变量和全局变量·样,数据都存放在全局区域,所以在主程序之前,编译 器已经为其分配好了内存,但在C和C++中静态局部变量的初始化节点又有点不太 样。在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行 初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化,在程 序运行结束,变量所处的全局内会被全部回收。 3)而在CH中,初始化时在执行相关代码时才会进行初始化,主要是由于CH引入对 象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中 经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以C++ 标准定为全局或静态对象是有首次用到时才会进行构造,并通过 atexit来管理。 在程序结束,按照构造顺序反方向进行逐个析构。所以在CH中是可以使用变量对 静态局部变量进行初始化的。 7. const? 1)阻止一个变量被改变,可以使用 cons t关键字。在定乂该 const变量时,通常需要 对它进行初始化,因为以后就没有机会再去改变它了 2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const, 或二者同时指定为 cons t; 3)在·个函数声明中, cons t可以修饰形参,衣明它是个输入参数,在函数内部不 能改变其值 4)对于类的成员函数,若指定其为 cons t类型,则表明其是一个常函数,不能修改类 的成员变量,类的常对象只能访问类的常成员函数; 5)对于类的成员函数,有时候必须指定其返回值为 const类型,以使得其返回值不为 左值 6) const成员函数可以访问非 const对象的非 cons t数据成员、 const数据成员,也 可以访问 cons t对象内的所有数据成员 7)非 cons t成员函数可以访问非 cons t对象的非 cons t数据成员、 coust数据成员, 但不可以访问 cons t对象的任意数据成员 8)个没有明确声明为 const的成员函数被看作是将要修改对象中数据成员的函数, 而且编译器不允许它为一个 const对象所调用。因此 cons t对象只能调用 cons t成 员函数。 9) const类型变量可以通过类型转换符 const cast将 const类型转换为非 const类 l0) const类型变量必须定义的时候进行初始化,因此也导致如果类的成员变量有 const 类型的变量,那么该变量必须在类的初始化列表中进行初始化 1)对于函数值传递的情况,因为参数传递是通过复制实参创建一个临时变量传递进函 数的,函数内只能改变临时变量,但无法改变实参。则这个时候无论加不加 cons t 对实参不公产生任何景响。但是在引用或指针传递函数调用中,因为传进去的是 个引用或指针,这样函数内部可以改变引用或指针所指向的变量,这时 const才是 实实在在地保护」实参所指向的变量。因为在编译阶段编详器对调用函数的选择是 根据实参进行的,所以,只有引用传递和指针传递可以用是否加 const来重载。 个拥有顶层 const的形参无法和另一个没有顶层 const的形参区分开来。 8. const成员函数的理解和应用? ① const stock& Stock: topal(② const stock&s)③ const ①处 const:确保返回的 Stock对象在以后的使用中不能被修改 ②处 const:确保此方法不修改传递的参数S ③处 const:保证此方法不修改调用它的对象, const对象只能调用 const成员函 数,不能调用非 cons t函数 9.指针和 const的用法 1)当 const修饰指针时,由于 const的位置不同,它的修饰对象会有所不同。 2)int* const p2中 cons t修饰p2的值,所以理解为p2的值不可以改变,即p2只能指 向固定的一个变量地址,但可以通过*2读写这个变量的值。顶层指针表示指针本身 是一个常量 3) int const*p1或者 const int*pl两种情况中 const修饰*p1,所以理解为*p1的值 不可以改变,即不可以给*1赋值改变pl指向变量的值,但可以通过给p赋值不同的 地址改变这个指针指向。底层揞针表小指针所指向的变量是一个常量。 4) int const *const p 10. mutable 1)如果需要在 const成员方法中修改一个成员变量的值,那么需要将这个成员变量修饰 为 mutable。即用 mutable修饰的成员变量不受 const成员方法的限制 2)可以认为 mutable的变量是类的辅助状态,但是只是起到类的一些方血表述的功能, 修改他的内容我们可以认为对象的状态本身并没有改变的。实际上由于 const cast 的存在,这个概念很多时候用处不是很到了。 11. extern用法? 1) extern修饰变量的声明 如果文件a.c需要引用b.c中变量intv,就可以在a.c中声明 extern int v,然后 就可以引用变量v 2) extern修饰函数的声明 如果文件a.c需要引用b.c中的函数,比如在b.c中原型是 int fun( int mu),那么 就可以在a.c中声明 extern int fun( Int mu),然后就能使用fun来做任何事 情。就像变量的声明一样, extern int fur(int)可以放在a.c中任何地方 而不一定非要放在a.c的文件作用域的范围中 3) extern修饰符可用于指示C或者C+十腑数旳调用规范。 比如在C++中调用C库函数,就需要在C++程序中用 extort“C”声明要引用的 函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范米链接。主要原 因是C十十和C程序编详完成后在目标代码中命名规则不同 12.int转字符串字符串转int? Dstrcat, strcpy, strncpy, memset; memcpy的 内部实现 c++11标准增加了全局函数std: to string 可以使用std:stoi/stol/ stoll等等函数 strcpy拥有返回值,有时候函数原本不需要返回值,但为了增加灵活性如支持链式衣达, 13深拷贝与浅拷贝? 1)浅复制—只是拷贝了基木类型的数据,而引用类型数据,复制后也是会发生引 用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被 复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改 深复制一-在计算机中开辟了一块新的内存地址用于存放复制的对象 Student sl 内存 Student/s2(s1) 1次构造,两次析 ame指针 构,内存泄漏 61和2中包含的指针对象同时指向一块内 存,析构时 delete了两次这个内存块就出错 深拷贝 Student s1 内存1 Student s2(s1) 容一样 内存2 勾造s2时拷贝一块和s1指向数据块一样大的数据块,并将 直拷贝下来,这样s1和s2指向各自的效据块,析构时释放 各自的叛据 综上所述,浅拷以是只对针进行拷贝,个吉指向同一个内存块,深持以是对指计和指针詣向的内容都进行拷贝,拷 贝后的指针是指不同闪的针。 2)在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对 象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已 经中请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B 把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。 14.C++模板是什么,底层怎么实现的? 1)编译器并不是把函数模板处理成能够处理仼意类的函数;编译器从函数模板通过具 体类型产生不同的函数;编译器会对函数模板进行两次编译:在声明的地方对模板 代码本身进行编译,在调用的地方对参数替换后的代码进行编译。 2)这是因为函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中 包含函数模板的头文件,如果该头文件中只有声明,没有定义,那编译器无法实例 化该模板,最终导致链接错误 15.C语言 struct和C++ struct区别 1)C语言中: struct是用户自定义数据类型(UT);CH中 struc t是抽象数据类型 (ADT),支持成员函数的定义,(C++中的 struc t能继承,能实现多态) 2)C中 struct是没有权限的设置的,且 struct中只能是一些变量的集合体,可以封 装数据却不可以隐藏数据,而且成员不可以是函数。 3)C++中, struc t的成员默认访问说明符为 public(为了与C兼容), class中的默 认访问限定符为 private, struct增加了访问权限,且可以和类一样有成员函数。 4) struct作为类的一种特例是用来自定义数据结构的。一个结构标记声明后,在C中 必须在结构标记前加上 struct,才能做结构类型名 16.虚函数可以声明为 inline吗? 1)虚函数用于实现运行时的多态,或者称为晚绑定或动态绑定。而内联函数用于提高 效率。内联函数的原理是,在编译期间,对调用内联函数的地方的代码替换成函数 代码。内联函数对于程序中需要频繁使用和调用的小函数非常有用。 2)虚函数要求在运行吋进行类型确定,而内敛函数要求在编译期完成相关的函数替换; 17.类成员初始化方式?构造函数的执行顺序?为什么用成员初始 化列表会快一些? 1)赋值初始化,通过在函数体内进行赋值初始化;列表初始化,在冒号后使用初始化 列表进行初始化。 这两种方式的主要区别在于: 对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的。 列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员 只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),那么分 配了内存空间后在进入函数体之前给数据成员赋值,就是说初始化这个数据成员 此时函数体还未执行。 2)一个派生类构造函数的执行顺序如下 ①虛拟棊类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。 ②基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。 ③类类型的成员对象的构造函数(按照初始化顺序) ④派生类自己的构造函数。 方法·是在构造函数当中做赋值的操作,而方法二是做纯粹的初始化操作。我们 都知道,C++的赋值操作是会产生临时对象的。临时对象的出现会降低程序的效 18成员列表初始化? 1)必须使用成员初始化的四种情况 ①当初始化一个引用成员时; ②当初始化一个常量成员时 3)当调用一个基类的构造函数,而它拥有一组参数时; ④当调用个成员类的构造函数,而它拥有·组参数时 2)成员初始化列表做了什么 ①编译器会—一操作初始化列表,以适当的顺序在构造凼数之内安插初始化操 作,并且在任何显示用户代码之前 ②1ist中的项日顺序是由类中的成员声明顺序决定的,不是由初始化列表的顺 序决定的 19构造函数为什么不能为虚函数?析构函数为什么要虚函数? 从存储空间角度,虚函数相应一个指向 vtable虚函数表的指针,这大家都知道, 但是这个指向 vtable的指针事实上是存储在对象的内存空间的。问题出来了,假设构 造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间 还没有,怎么找 vtable呢?所以构造函数不能是虚函数。 2.从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调 用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函 数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候可 以变成调用子类的那个成员函数。而构造函数是在创建对象时自己主动调用的,不可 能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3.构造凶数不须要是虚函数,也不同意是虚函数,由」创建一个对象时我们总是要明 白指定对象的类型,虽然我们可能通过实验室的基类的指针或引用去訪问它但析构却 不定,我们往往通过基类的指针来销毁对象。这时候假设析构函数不是虚函数,就 不能正确识别对象类型从而不能正确调用析构函数。 4.从实现上看,vbt在构造函数调用后才建立,因而构造函数不可能成为虚函数从实 际含义上看,在调用构造函数时还不能确定对象的真实类型(由于子类会调父类的构 造睬数);并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次,不是对 象的动态行为,也没有必要成为虚函数。 5.当一个构造函数被调用时,它做的首要的事情之中的一个是初始化它的WPTR。因 此,它仅仅能知道它是“当前”类的,而全然忽视这个对象后面是否还有继承者。当 编译器为这个构造函数产生代码时,它是为这个类的构造函数产生代码一一既不是为 基类,也不是为它的派生类(由于类不知道谁继承它)。所以它使用的VPTR必须是对 于这个类的 VTABLE。并且,仪仅要它是最后的构造函数调用,那么在这个对象的生命 期内,WPTR将保持被初始化为指向这个 VTABLE,但假设接着另一个史晚派生的构造函 数被调用,这个构造函数又将设置WPTR指向它的 VTABLE,等.直到最后的构造函数结 束。VPTR的状态是由被最后调用的构造函数确定的。这就是为什么构造函数调用是从 基类到更加派生类顺序的还有一个理由。可是,当这一系列构造数调用正发生时 每一个构造函数都已经设置VPTR指向它自己的 VTABLE。假设函数调用使用虚机制,它 将仅仅产生通过它自己的 VTABLE的调用,而不是最后的 VTABLE(全部构造函数被调用 后才会有最后的 VTABLE) 因为构造函数本来就是为了明确初始化对象成员才产生的,然而 virtual function主要是为了再不完全了解细节的情况下也能正确处理对象。另外, virtual 函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用 virtual 数来完成你想完成的动作 直接的讲,C++中基类采用 virtual虚析构函数是为了防止内存泄漏。具体地说, 如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基 类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑 定,因而只会调用基类的析构函数,而不会调用派生类的析构函数ε那么在这种情况 卜,派生类中中请的空问就得不到释放从而产生内存泄漏。所以,为了防止这种情況 的发生,C++中基类的析构函数应采用 virtual虚析构函数。

...展开详情
试读 127P C++面试题集锦.pdf
立即下载 身份认证后 购VIP低至7折
一个资源只可评论一次,评论内容不能少于5个字
您会向同学/朋友/同事推荐我们的CSDN下载吗?
谢谢参与!您的真实评价是我们改进的动力~
关注 私信
上传资源赚钱or赚积分
最新推荐
C++面试题集锦.pdf 49积分/C币 立即下载
1/127
C++面试题集锦.pdf第1页
C++面试题集锦.pdf第2页
C++面试题集锦.pdf第3页
C++面试题集锦.pdf第4页
C++面试题集锦.pdf第5页
C++面试题集锦.pdf第6页
C++面试题集锦.pdf第7页
C++面试题集锦.pdf第8页
C++面试题集锦.pdf第9页
C++面试题集锦.pdf第10页
C++面试题集锦.pdf第11页
C++面试题集锦.pdf第12页
C++面试题集锦.pdf第13页
C++面试题集锦.pdf第14页
C++面试题集锦.pdf第15页
C++面试题集锦.pdf第16页
C++面试题集锦.pdf第17页
C++面试题集锦.pdf第18页
C++面试题集锦.pdf第19页
C++面试题集锦.pdf第20页

试读结束, 可继续阅读

49积分/C币 立即下载