C++笔试面试考点全Word文档格式.docx
《C++笔试面试考点全Word文档格式.docx》由会员分享,可在线阅读,更多相关《C++笔试面试考点全Word文档格式.docx(30页珍藏版)》请在冰点文库上搜索。
从静态存储区域分配。
内存在程序编译的时候已经分配好,这块内存在程序的整个运行期间都存在。
如全局变量。
在栈上创建。
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
栈内存分配运算内置于处理器的指令集中,效率高,但是分配的内存容量有限。
从堆上分配,亦称动态内存分配。
程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。
动态内存的生存期由我们决定,使用非常灵活。
BOOL、float、指针变量与”零值比较的if语句”。
BOOL:
If(flag)或if(!
flag)
Float:
constfloatEPSINON=0.00001;
If((x>
=.EPSINON)&
&
(x<
=EPSINON))说明:
不可将浮点变量用”==”或”!
=”与数字比较,应该设法转化成”>
=”或”<
=”此类形式。
指针*p:
if(p==NULL)if(p!
=NULL)
#include<
filename.h>
和#include“filename.h”有什么区别
对于#include<
,编译器从标准库路径开始搜索filename.h,对于#include“filename.h”,编译器从用户的工作路径中开始搜索filename.h
在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”?
C++语言支持函数重载,C语言不支持函数重载。
函数被C++编译后在库中的名字与C语言的不同。
假设某个函数的原型为:
voidfee(intx,inty);
该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
C++提供了C连接交换指定符号extern“C”来解决名字匹配的问题。
引用与指针有什么区别?
1)引用必须被初始化,指针不必。
2)引用初始化以后不能被改变,指针可以改变所指的对象。
3)不存在指向空值的引用,但是存在指向空值的指针。
变量的声明和定义有什么区别
从编译原理上来说,声明是仅仅告诉编译器,有个某类型的变量会被使用,但是编译器并不会为它分配任何内存。
而定义就是分配了内存。
Sizeof和strlen区别
1、Sizeof操作符的结果类型是size_t,它在头文件中typedef为unsignedint类型。
该类型保证能容纳实现所建立的最大对象的字节大小。
2、Sizeof是运算符,strlen是函数
3、Sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以换行符”\0″结尾的。
4、Strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小。
5、数组做sizeof的参数不退化,传递给strlen就退化为指针;
malloc与new的区别
1.new是C++中的操作符,malloc是C中的一个函数;
2.new不只是分配内存,而且会调用类的构造函数,同理delete会调用类析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数。
3.内存泄露对于malloc或者new都可以检查出来的,区别在于new可以指明那个文件的那一行,而malloc没有这些信息。
New可以认为是malloc加构造函数的执行。
New出来的指针是直接带类型信息。
而malloc返回的都是void指针。
简述#define#endif和#ifndef的作用
#define指示接受一个名字并定义该名字为预处理器变量;
#ifndef检测指定的预处理变量是否定义;
#endif预处理未定义
cin>
>
temp;
unsignedintconstsize2=temp;
charstr2[size2];
str2定义出错,size2非编译器期间常量,而数组定义要求长度必须编译期常量。
编写strcpy函数
已知strcpy函数的原型是char*strcpy(char*strDest,constchar*strSrc);
其中strDest是目的字符串,strSrc是源字符串。
char*strcpy(char*strDest,constchar*strSrc)
{
assert((strDest!
=NULL)&
(strSrc!
=NULL));
char*address=strDest;
while((*strDest++=*strSrc++)!
=’\0′)
NULL;
}
returnaddress;
strycpy能把strSrc的内容复制到strDest,为什么还要char*类型的返回值?
为了实现链式表达式。
如:
intlength=strlen(strcpy(strDest,”helloworld”));
编写类String的构造函数、析构函数和赋值函数
classString
public:
String(Constchar*str=NULL);
//普通构造函数
String(constString&
other);
//拷贝构造函数
~String(void);
//析构函数
String&
operate=(constString&
//赋值函数
private:
char*m_data;
//用于保存字符串
};
//String的析构函数
String:
:
~String(void)
delete[]m_data;
//由于m_data是内部数据类型,也可以写成deletem_data;
//String的普通构造函数
String(constchar*str)
If(str==NULL)
m_data=newchar[1];
*m_data=‘\0′;
else
intlength=strlen(str);
m_data=newchar[length+1];
strcpy(m_data,str);
other)
intlength=strlen(other.m_data);
strcpy(m_data,other.m_data);
String&
operate=(constString&
//1.检查自赋值
If(this==&
other)\
return*this;
//2.释放原有的内存资源
Delete[]m_data;
//3.分配新的内存资源,并复制内容
m_data=newchar[length+1];
对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
C用宏定义,C++用inline
交换两个变量的值,不使用第三个变量。
即a=3,b=5,交换之后a=5,b=3;
两种解法,一种是用算术算法,一种是用^(异或)
a=a+b;
b=a-b;
a=a-b;
or
a=a^b;
//只能对int,char
b=a^b;
a^=b^=a;
全局变量和局部变量在内存中是否有区别?
如果有,是什么区别?
答、全局变量储存在静态数据区,局部变量在堆栈中。
什么函数不能声明为虚函数?
答:
构造函数(constructor)
不能做switch()的参数类型是:
答、switch的参数不能为实型。
如何引用一个已经定义过的全局变量?
答、可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变量写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错
C++是不是类型安全的?
答案:
不是。
两个不同类型的指针之间可以强制转换(用reinterpretcast)
当一个类A中没有声明任何成员变量与成员函数,这时sizeof(A)的值是多少,请解释一下编译器为什么没有让它为零。
为1。
举个反例,如果是零的话,声明一个classA[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。
C++函数中值的传递方式
有三种方式:
值传递、指针传递、引用传递
内存的分配方式
分配方式有三种,
1、静态存储区,是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。
2、栈上分配,函数内的局部变量就是从这分配的,但分配的内存容易有限。
3、堆上分配,也称动态分配,如我们用new,malloc分配内存,用delete,free来释放的内存。
用什么函数开启新进程、线程。
线程:
CreateThread/AfxBeginThread等
进程:
CreateProcess等
SendMessage和PostMessage有什么区别
SendMessage是阻塞的,等消息被处理后,代码才能走到SendMessage的下一行。
PostMessage是非阻塞的,不管消息是否已被处理,代码马上走到PostMessage的下一行。
CMemoryState主要功能是什么
查看内存使用情况,解决内存泄露问题。
系统会自动打开和关闭的3个标准的文件是?
(1)
标准输入—-键盘—stdin
(2)
标准输出—-显示器—stdout
(3)
标准出错输出—-显示器—stderr
strcpy()和memcpy()的区别?
strcpy()和memcpy()都可以用来拷贝字符串,strcpy()拷贝以’\0’结束,但memcpy()必须指定拷贝的长度。
总结static的应用和作用?
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
指针的几种典型应用情况?
int*p[n];
—–指针数组,每个元素均为指向整型数据的指针。
int(*)p[n];
—p为指向一维数组的指针,这个一维数组有n个整型数据。
int*p();
——函数带回指针,指针指向返回的值。
int(*)p();
—-p为指向函数的指针。
程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。
在什么时候使用常引用?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。
windows消息系统由哪几部分构成?
由以下3部分组成:
1.
消息队列:
操作系统负责为进程维护一个消息队列,程序运行时不断从该消息队列中获取消息、处理消息;
2.
消息循环:
应用程序通过消息循环不断获取消息、处理消息。
3.
消息处理:
消息循环负责将消息派发到相关的窗口上使用关联的窗口过程函数进行处理。
在头文件中进行类的声明,在对应的实现文件中进行类的定义有什么意义?
这样可以提高编译效率,因为分开的话只需要编译一次生成对应的.obj文件后,再次应用该类的地方,这个类就不会被再次编译,从而大大的提高了编译效率。
C++编译器自动为类产生的四个缺省函数是什么?
默认构造函数,拷贝构造函数,析构函数,赋值函数。
拷贝构造函数在哪几种情况下会被调用?
1.当类的一个对象去初始化该类的另一个对象时;
2.如果函数的形参是类的对象,调用函数进行形参和实参结合时;
3.如果函数的返回值是类对象,函数调用完成返回时。
什么时候必须重写拷贝构造函数?
当构造函数涉及到动态存储分配空间时,要自己写拷贝构造函数,并且要深拷贝。
不允许重载的5个运算符是哪些?
.*(成员指针访问运算符号)
:
:
域运算符
Sizeof长度运算符号
4.
?
条件运算符号
5.
.(成员访问符)
函数重载是什么意思?
它与虚函数的概念有什么区别?
函数重载是一个同名函数完成不同的功能,编译系统在编译阶段通过函数参数个数、参数类型不同,函数的返回值来区分该调用哪一个函数,即实现的是静态的多态性。
但是记住:
不能仅仅通过函数返回值不同来实现函数重载。
而虚函数实现的是在基类中通过使用关键字virtual来申明一个函数为虚函数,含义就是该函数的功能可能在将来的派生类中定义或者在基类的基础之上进行扩展,系统只能在运行阶段才能动态决定该调用哪一个函数,所以实现的是动态的多态性。
它体现的是一个纵向的概念,也即在基类和派生类间实现。
delete与delete[]区别:
delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数。
继承的优缺点。
1、类继承是在编译时刻静态定义的,且可直接使用,
2、类继承可以较方便地改变父类的实现。
缺点:
1、因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现
2、父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为
3、如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。
这种依赖关系限制了灵活性并最终限制了复用性。
在编写C++赋值运算符时有哪些要注意的地方?
返回值,参数最好用引用
减少友元函数使用,移植有问题.
strcpy()容易引起缓冲区溢出问题,请问有什么函数可以替代以减少风险,为什么?
Strncpy功能:
将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样只有遇到NULL才停止复制,而是多了一个条件停止,就是说如果复制到第n个字符还未遇到NULL,也一样停止),返回指向dest的指针。
、Strcpy和Strncpy的区别--
第一种情况:
char*p="
howareyou?
"
;
charname[20]="
ABCDEFGHIJKLMNOPQRS"
strcpy(name,p);
//name改变为"
"
====>
正确!
strncpy(name,p,sizeof(name));
//name改变为"
=====>
后续的字符将置为NULL
第二种情况:
charname[10];
//目标串长度小于源串,错误!
name[sizeof(name)-1]='
\0'
//和上一步组合,弥补结果,但是这种做法并不可取,因为上一步出错处理方式并不确定
strncpy(name,p,sizeof(name));
//源串长度大于指定拷贝的长度sizeof(name),注意在这种情况下不会自动在目标串后面加'
name[sizeof(name)-1]='
//和上一步组合,弥补结果
将“引用”作为函数参数有哪些特点?
(1)传递引用给函数与传递指针的效果是一样的。
这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。
(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;
而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;
如果传递的是对象,还将调用拷贝构造函数。
因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用”*指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性较差;
另一方面,在主调函数的调用点处,必须用变量的地址作为实参。
而引用更容易使用,更清晰
将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?
格式:
类型标识符&
函数名(形参列表及类型说明){//函数体}
好处:
在内存中不产生被返回值的副本;
(注意:
正是因为这点原因,所以返回一个局部变量的引用是不可取的。
因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtimeerror!
注意事项:
(1)不能返回局部变量的引用。
这条可以参照EffectiveC++[1]的Item31。
主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。
(2)不能返回函数内部new分配的内存的引用。
虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。
例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memoryleak。
(3)可以返回类成员的引用,但最好是const。
这条原则可以参照EffectiveC++[1]的Item30。
主要原因是当对象的属性是与某种业务规则(businessrule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。
如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
(4)流操作符重载返回值申明为“引用”的作用:
流操作符<
<
和>
,这两个操作符常常希望被连续使用,例如:
cout<
“hello”<
endl;
因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。
可选的其它方案包括:
返回一个流对象和返回一个流对象指针。
但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<
操作符实际上是针对不同对象的!
这无法让人接受。
对于返回一个流指针则不能连续使用<
操作符。
因此,返回一个流对象引用是惟一选择。
这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。
赋值操作符=。
这个操作符象流操作符一样,是可以连续使用的,例如:
x=j=10;
或者(x=10)=100;
赋值操作符的返回值必须是一个
(5)在另外的一些操作符中,却千万不能返回引用:
+-*/四则运算符。
它们不能返回引用,EffectiveC++[1]的Item23详细的讨论了这个问题。
主要原因是这四个操作符没有sideeffect,因此,它们必须构造一个对象作为返回值,可选的方案包括:
返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。
根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。
静态对象的引用又因为((a+b)==(c+d))会永远为true而导致错误。
所以可选的只剩下返回一个对象了。
左值,以便可以被继续赋值。
因此引用成了这个操作符的惟一返回值选择。
h头文件中的ifndef/define/endif的作用?
防止该头文件被重复引用。
面向对象的三个基本特征,并简单叙述之?
1.封装:
将客观事物抽象成类,每个类对自身的数据和方法实行protection(private,protected,public)
2.继承:
广义的继承有三种实现形式:
实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使