C++笔试面试题整理

朋友给出的一些常见的C++面试题,特整理以下,后期遇到新的再更新。c++

面试题

列举并解释C++中的四种运算符转化,说明它们的不一样点:
程序员

  • static_cast: 在功能上基本上与C风格的类型转换同样强大,含义也同样。它也有功能上限制。例如,你不能用static_cast象用C风格的类型转换同样把struct转换成int类型或者把double类型转换成指针类型,另外,static_cast不能从表达式中去除const属性,由于另外一个新的类型转换操做符const_cast有这样的功能。
  • const_cast: 用于类型转换掉表达式的constvolatileness属性。经过使用const_cast,你向人们和编译器强调你经过类型转换想作的只是改变一些东西的constness或者 volatileness属性。这个含义被编译器所约束。若是你试图使用const_cast来完成修改constness 或者volatileness属性以外的事情,你的类型转换将被拒绝。
  • dynamic_cast: 它被用于安全地沿着类的继承关系向下进行类型转换。这就是说,你能用dynamic_cast把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,并且你能知道转换是否成功。失败的转换将返回空指针(当对指针进行类型转换时)或者抛出异常(当对引用进行类型转换时)。
  • reinterpret_cast: 使用这个操做符的类型转换,其的转换结果几乎都是执行期定义(implementation-defined。所以,使用reinterpret_casts的代码很难移植。reinterpret_casts的最普通的用途就是在函数指针类型之间进行转换。

 

什么是封装?C++中是如何实现的?面试

封装来源于信息隐藏的设计理念,是经过特性和行为的组合来建立新数据类型让接口与具体实现相隔离编程

C++中是经过类来实现的,为了尽可能避免某个模块的行为干扰同一系统中的其它模块,应该让模块仅仅公开必须让外界知道的接口。数组

 

什么是动态特性?安全

在绝大多数状况下,程序的功能是在编译的时候就肯定下来的,咱们称之为静态特性。多线程

反之,若是程序的功能是在运行时刻才能肯定下来的,则称之为动态特性。编程语言

C++中,虚函数,抽象基类,动态绑定和多态构成了出色的动态特性。函数

 

对象在内存中是怎么存放的?布局

在类对象的内存布局中,若是有虚函数,首先是该类的vtbl指针,而后才是对象数据,对象数据都是顺序存放,固然会涉及到字节对齐,这样会带来存取效率的提高

 

给你一个指针,并用new动态申请空间,在另外一个函数中释放,不知道是申请的一个元素仍是一个数组的状况下,怎么肯定用delete仍是delete []

不一样的编译器有不一样的实现机制,比较经常使用的有两种:

  1. new ,在第一个对象前面记录分配了多少对象.
  2. 使用键值,key-value
For ex:

int *p = new int[n];

//p为key,n为value.

  

C++const有什么做用?至少说明3

  • const用于定义常量:const定义的常量编译器能够对其进行数据静态类型安全检查。
  • const修饰函数形式参数:当输入参数为用户自定义类型和抽象数据类型时,将“值传递”改成“const&传递”能够提升效率。
  • const修饰函数的返回值:若是给“指针传递”的函数返回值加const,则返回值不能被直接修改,且该返回值只能被赋值给const修饰的同类型指针。
  • const修饰类的成员函数(函数定义体):任何不须要修改数据成员的函数都应该使用const修饰,这样即便不当心修改了数据成员或调用了非const成员函数,编译器也会报错。当const函数中使用到的变量被mutable修饰后,在const函数中能够对其进行修改。常函数只能调用类中的常函数,不能调用很是函数。

 

 

C语言的volatile的含义是什么。使用时会对编译器有什么暗示。

volatile的意思是易变的,也就是说,在程序运行过程当中,有一些变量可能会被莫名其妙的改变,而优化器为了节约时间,有时候不会重读这个变量的真实值,而是去读在寄存器的备份,这样的话,这个变量的真实值反而被优化器给“优化”掉了,用时髦的词说就是被“和谐”了。若是使用了这个修饰词,就是通知编译器别犯懒,老老实实去从新读一遍!可能我说的太“通俗”了,那么我引用一下“大师”的标准解释: volatile的本意是“易变的”。因为访问寄存器的速度要快过RAM,因此编译器通常都会做减小存取外部RAM的优化,但有可能会读脏数据。当要求使用volatile声明的变量的值的时候,系统老是从新从它所在的内存读取数据,即便它前面的指令刚刚从该处读取过数据。并且读取的数据马上被保存。精确地说就是,优化器在用到这个变量时必须每次都当心地从新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1).并行设备的硬件寄存器(如:状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3).多线程应用中被几个任务共享的变量嵌入式系统程序员常常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难

 

线程同步的方式

互斥锁、条件变量和信号量

 

说下你对内存的了解?

1.-由编译器自动分配释放

2.-通常由程序员分配释放,若程序员不释放,程序结束时可能由OS回收

3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另外一块区域。-程序结束释放

4.另外还有一个专门放常量的地方。-程序结束释放

5程序代码区,存放2进制代码。

在函数体中定义的变量一般是在栈上,用malloccallocrealloc等分配内存的函数分配获得的就是在堆上。在全部函数体外定义的是全局量,加了static修饰符后无论在哪里都存放在全局区(静态区),在全部函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,函数中的"adgfdf"这样的字符串存放在常量区。

 

 

在何时须要使用“常引用”?

若是既要利用引用提升程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const类型标识符 &引用名=目标变量名;

 

“引用”做为函数返回值类型的格式、好处和须要遵照的规则?

格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }

好处:在内存中不产生被返回值的副本;(注意:正是由于这点缘由,因此返回一个局部变量的引用是不可取的。由于随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!

注意事项:

1)不能返回局部变量的引用。这条能够参照Effective C++[1]Item 31。主要缘由是局部变量会在函数返回后被销毁,所以被返回的引用就成为了"无所指"的引用,程序会进入未知状态。

2)不能返回函数内部new分配的内存的引用。这条能够参照Effective C++[1]Item 31。虽然不存在局部变量的被动销毁问题,可对于这种状况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是做为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就没法释放,形成memory leak

3)能够返回类成员的引用,但最好是const。这条原则能够参照Effective C++[1]Item 30。主要缘由是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值经常与某些其它属性或者对象的状态有关,所以有必要将赋值操做封装在一个业务规则当中。若是其它对象能够得到该属性的很是量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

4)流操做符重载返回值申明为“引用”的做用:

流操做符<<>>,这两个操做符经常但愿被连续使用,例如:cout << "hello" << endl;所以这两个操做符的返回值应该是一个仍然支持这两个操做符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。可是对于返回一个流对象,程序必须从新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操做符其实是针对不一样对象的!这没法让人接受。对于返回一个流指针则不能连续使用<<操做符。所以,返回一个流对象引用是唯一选择。这个惟一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的缘由吧。

赋值操做符=。这个操做符象流操做符同样,是能够连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操做符的返回值必须是一个左值,以即可以被继续赋值。所以引用成了这个操做符的唯一返回值选择。

 

全局变量和局部变量有什么区别?是怎么实现的?操做系统和编译器是怎么知道的?

生命周期不一样:

全局变量随主程序建立和建立,随主程序销毁而销毁;局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;

使用方式不一样:经过声明后全局变量程序的各个部分均可以用到;局部变量只能在局部使用;分配在栈区。

操做系统和编译器经过内存分配的位置来知道的,全局变量分配在全局数据段而且在程序开始运行的时候被加载。局部变量则分配在堆栈里面。

与全局对象相比,使用静态数据成员有什么优点?

主要有如下所述两种优点。

静态数据成员没有进入程序的全局名字空间,所以不存在程序中其余全局名字冲突的问题。

使用静态数据成员能够隐藏信息。由于静态成员能够是Private成员,而全局对象不能。

 

有哪几种状况只能用初始化列表,而不能用赋值?

当类中含有const、引用成员变量以及基类的构造函数都须要初始化列表。

 

虚函数是怎么实现的?

简单地说,虚函数是经过虚函数表实现的。事实上,若是一个类中含有虚函数,则系统会为这个类分配一个指针成员指向一张虚函数表(vtbl),表中每一项指向一个虚函数的地址,实现上就是一个函数指针的数组。

 

什么是多态?

答:多态是指相同的操做或函数、过程可做用于多种类型的对象上并得到不一样的结果。不一样的对象,收到同一消息能够产生不一样的结果,这种现象称为多态。

 

请用简单的语言告诉我C++是什么?

C++是在C语言的基础上开发的一种面向对象编程语言,应用普遍。C++支持多种编程范式--面向对象编程、泛型编程和过程化编程。其编程领域众广,经常使用于系统开发,引擎开发等应用领域,是最受广大程序员受用的最强大编程语言之一,支持类:类、封装、重载等特性!

 

newdeletemallocfree关系

delete会调用对象的析构函数,new对应free只会释放内存,

new调用构造函数。

mallocfreeC++/C语言的标准库函数,new/deleteC++的运算符。它们均可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free没法知足动态对象的要求。对象在建立的同时要自动执行构造函数,对象在消亡以前要自动执行析构函数。因为malloc/free是库函数而不是运算符,不在编译器控制权限以内,不可以把执行构造函数和析构函数的任务强加于malloc/free。所以C++语言须要一个能完成动态内存分配和初始化工做的运算符new,以及一个能完成清理与释放内存工做的运算符delete。注意new/delete不是库函数。

 

main函数执行之前,还会执行什么代码?

全局对象的构造函数会在main函数以前执行。

 

全局变量和局部变量有什么区别?是怎么实现的?操做系统和编译器是怎么知道的?

生命周期不一样:

全局变量随主程序建立和建立,随主程序销毁而销毁;局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;

使用方式不一样:经过声明后全局变量程序的各个部分均可以用到;局部变量只能在局部使用;分配在栈区。

操做系统和编译器经过内存分配的位置来知道的,全局变量分配在全局数据段而且在程序开始运行的时候被加载。局部变量则分配在堆栈里面。

 

指针和引用的区别?

1.指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用仅是个别名;

2.引用使用时无需解引用(*),指针须要解引用;

3.引用只能在定义时被初始化一次,以后不可变;指针可变;

4.引用没有 const,指针有 const

5.引用不能为空,指针能够为空;

6.sizeof引用”获得的是所指向的变量(对象)的大小,而“sizeof指针”获得的是指针自己的大小;

7.指针和引用的自增(++)运算意义不同;

8.指针能够有多级,可是引用只能是一级(int **p;合法而 int &&a是不合法的)

9.从内存分配上看:程序为指针变量分配内存区域,而引用不须要分配内存区域。

 

静态函数存在的意义?

静态私有成员在类外不能被访问,可经过类的静态成员函数来访问;

当类的构造函数是私有的时,不像普通类那样实例化本身,只能经过静态成员函数来调用构造函数。

 

是否是一个父类写了一个virtual函数,若是子类覆盖它的函数不加virtual,也能实现多态?

virtual修饰符会被隐形继承的。

virtual可加可不加,子类覆盖它的函数不加virtual,也能实现多态。

 

函数重载是什么意思?它与虚函数的概念有什么区别?

函数重载是一个同名函数完成不一样的功能,编译系统在编译阶段经过函数参数个数、参数类型不一样,函数的返回值来区分该调用哪个函数,即实现的是静态的多态性。可是记住:不能仅仅经过函数返回值不一样来实现函数重载。而虚函数实现的是在基类中经过使用关键字virtual来申明一个函数为虚函数,含义就是该函数的功能可能在未来的派生类中定义或者在基类的基础之上进行扩展,系统只能在运行阶段才能动态决定该调用哪个函数,因此实现的是动态的多态性。它体现的是一个纵向的概念,也即在基类和派生类间实现。

 

deletedelete[]区别:

delete只会调用一次析构函数,而delete[]会调用每个成员的析构函数。

 

继承的优缺点。

1、类继承是在编译时刻静态定义的,且可直接使用,

2、类继承能够较方便地改变父类的实现。

缺点:

1、由于继承在编译时刻就定义了,因此没法在运行时刻改变从父类继承的实现

2、父类一般至少定义了子类的部分行为,父类的任何改变均可能影响子类的行为

3、若是继承下来的实现不适合解决新的问题,则父类必须重写或被其余更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

 

在何时须要使用“常引用”?

若是既要利用引用提升程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。

 

什么函数不能声明为虚函数?

构造函数(constructor

 

不能作switch()的参数类型是:

switch的参数不能为实型。

 

CMemoryState主要功能是什么

查看内存使用状况,解决内存泄露问题。

 

简述全局变量的优缺点?

全局变量也称为外部变量,它是在函数外部定义的变量,它属于一个源程序文件,它保存上一次被修改后的值,便于数据共享,但不方便管理,易引发意想不到的错误。

 

什么是指针?谈谈你对指针的理解?

指针是一个变量,该变量专门存放内存地址;

指针变量的类型取决于其指向的数据类型,在所指数据类型前加*

指针变量的特色是它能够访问所指向的内存。

 

当一个类A中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,请解释一下编译器为何没有让它为零。

1。举个反例,若是是零的话,声明一个classA[10]对象数组,而每个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。

 

对于一个频繁使用的短小函数,C语言中应用什么实现,C++中应用什么实现?

c用宏定义,c++inline

 

描述实时系统的基本特性

在特定时间内完成特定的任务,实时性与可靠性。

 

友元关系有什么特性?

单向的,非传递的,不能继承的。

 

成员函数经过什么来区分不一样对象的成员数据?为何它可以区分?

答:经过this指针指向对象的首地址来区分的。

 

对象都具备的两方面特征是什么?分别是什么含义?

答:对象都具备的特征是:静态特征和动态特征。

静态特征是指能描述对象的一些属性(成员变量),动态特征是指对象表现出来的行为(成员函数)

 

在头文件中进行类的声明,在对应的实现文件中进行类的定义有什么意义?

这样能够提升编译效率,由于分开的话只须要编译一次生成对应的.obj文件后,再次应用该类的地方,这个类就不会被再次编译,从而大大的提升了编译效率。

 

在类外有什么办法能够访问类的非公有成员?

友元,继承,公有成员函数。

 

C++是在何时给变量分配的内存

函数内的局部变量是在函数体执行前分配空间。函数执行完毕后回收空间。

静态变量是在程序运行时分配空间。程序结束时回收空间。

使用new或者malloc建立的变量是在调用newmalloc函数的时候进行分配。调用deletefree函数的时候进行回收。

相关文章
相关标签/搜索