delete会调用对象的析构函数,和malloc对应free只会释放内存;
new调用构造函数。
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
参考回答:首先,new/delete是C++的关键字,而malloc/free是C语言的库函数,后者使用必须指明申请内存空间的大小,
对于类类型的对象,后者不会调用构造函数和析构函数
* C++具有封装、继承和多态三种特性
C++相比C,增加多许多类型安全的功能,比如强制类型转换、
C++支持范式编程,比如模板类、函数模板等
优点:类继承是在编译时刻静态定义的,且可直接使用,类继承可以较方便地改变父类的实现。
缺点:
封装,继承和多态。
在面向对象程序设计语言中,封装是利用可重用成分构造软件系统的特性,它不仅支持系统的可重用性,而且还有利于提高系统的可扩充性;消息传递可以实现发送一个通用的消息而调用不同的方法;封装是实现信息隐蔽的一种技术,其目的是使类的定义和实现分离。
析构函数调用的次序是先派生类的析构后基类的析构,也就是说在基类的的析构调用的时候,派生类的信息已经全部销毁了定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数;析构的时候恰好相反:先调用派生类的析构函数、然后调用基类的析构函数JAVA无析构函数深拷贝和浅拷贝
* 申明一个引用的时候,切记要对其进行初始化。
引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。
声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。
不能建立数组的引用。
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const类型标识符 &引用名=目标变量名;
例1
int;constint&=;=1;//错误=1;//正确例2
foo();voidbar(&);那么下面的表达式将是非法的:
bar(foo());bar(“hello world”);原因在于foo( )和"helloworld"串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。引用型参数应该在能被定义为const的情况下,尽量定义为const 。
格式:类型标识符 &函数名(形参列表及类型说明){//函数体 }
好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtimeerror!
注意事项:
* 不能返回局部变量的引用。这条可以参照EffectiveC++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
* 1
因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,
例如:x = j= 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。
例3
#include
在另外的一些操作符中,却千万不能返回引用:±*/四则运算符。它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。
引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。
例4:
A;B:A{…};;&=;
流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。
涉及到UML中的一些概念:关联是表示两个类的一般性联系,比如“学生”和“老师”就是一种关联关系;聚合表示has-a的关系,是一种相对松散的关系,聚合类不需要对被聚合类负责,如下图所示,用空的菱形表示聚合关系:从实现的角度讲,聚合可以表示为:
classA{…}classB{*;…}而组合表示contains-a的关系,关联性强于聚合:组合类与被组合类有相同的生命周期,组合类要对被组合类负责,采用实心的菱形表示组合关系:实现的形式是:
classA{…}classB{;…}
常考的题目。从定义上来说:
* 重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
重写:是指子类重新定义父类虚函数的方法。* 从实现原理上来说:
重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。
主要是两个:
除了“能够让应用程序处理存储于DBMS中的数据“这一基本相似点外,两者没有太多共同之处。但是Ado使用OLE DB 接口并基于微软的COM技术,而ADO.NET 拥有自己的ADO.NET 接口并且基于微软的.NET体系架构。众所周知.NET 体系不同于COM 体系,ADO.NET接口也就完全不同于ADO和OLE DB 接口,这也就是说ADO.NET和ADO是两种数据访问方式。ADO.net 提供对XML的支持。
都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而free 不会调用对象的destructor.
i 为30。
当类中含有const、reference成员变量;基类的构造函数都需要初始化表。
不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。
全局对象的构造函数会在main 函数之前执行。
在C++中,可以用struct和class定义类,都可以继承。区别在于:struct的默认继承权限和默认访问权限是public,而class的默认继承权限和默认访问权限是private。
另外,class还可以定义模板类形参,比如template
sizeof(A) = 1。编译器不允许一个类的大小为0。那是被编译器插进去的一个char ,使得这个class的不同实体(object)在内存中配置独一无二的地址。 也就是说这个char是用来标识类的不同对象的。肯定不是零。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。
通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。
C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast
:if(!)orif()int:if(==0)float:const=0.000001if(<&&>-):if(!=NULL)orif(==NULL)
Const作用:定义常量、修饰函数参数、修饰函数返回值三个作用。被Const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
数组 | 指针 |
---|---|
保存数据 | 保存数据的地址 |
直接访问数据 | 间接访问数据,首先获得指针的内容,然后将其作为地址,从该地址中提取数据 |
隐式的分配和删除 | 通常用于动态的数据结构 |
通常用于固定数目且数据类型相同的元素 | 通过Malloc分配内存,free释放内存 |
自身即为数据名 | 通常指向匿名数据,操作匿名函数 |
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。 成员函数被重载的特征: There are two int variables:a and b, don’t use “if”, “? :”, “switch”or other judgement statements, find outthe biggest one of the two numbers. 答案:( ( a + b ) + abs( a - b ) ) / 2 <<FILE;<<LINE;FILE和LINE是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。 可以,可以用_onexit 注册一个函数,它会在main之后执行int fn1(void), fn2(void),fn3(void), fn4 (void); #ifdef __cplusplus<<“c++”;#else<<“c”;#endif IP处在互连网络层。负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收)。 交换机属于OSI第二层即数据链路层设备。它根据MAC地址寻址,通过站表选择路由,站表的建立和维护由交换机自动进行。路由器属于OAI第三层即网络层设备,它根据IP地址进行寻址,通过路由表路由协议产生。交换机最大的好处是快速,路由器最大的好处是控制能力强。 8086微处理器共有4个16位的段寄存器,在寻址内存单元时,用它们直接或间接地存放段地址。 在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外时不能使用这些变量的,它们称为局部变量; 不同函数中可以使用名字相同的变量,它们代表不同的对象,互不干扰 在函数外定义的变量是外部变量,外部变量是全局变量,全局变量可以为本文件中其它函数所共用,它的有效范围从定义变量的位置开始到本源文件结束; 建议不再必要的时候不要使用全局变量,因为: b.它使函数的通用性降低了c.使用全局变量过多,会降低程序的清晰性* 在程序运行期间分配固定的存储空间的变量,叫做静态变量 不是 程序在执行时,因为会首先初始化全局变量,当这个变量是一个对象时,则会首先调用该对象的构造函数,所以上例中,a的构造函数先执行,然后再执行main()函数,C++中并非所有的动作都是main()函数引起的 就是被调用者回头调用的函数,它是通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所所指向的函数时,此时,就可以称它为回调函数。 回调函数不是由该函数的实现方直接调用的,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 (1)声明 回调函数是高层提供给低层的调用,对于低层它是未知的,必须由高层进行安装,这个安装函数就是一个低层提供的API,安装后低层不是道这个回调的名字,但它通过一个函数指针来保存这个回调函数,在需要调用时,只需引用这个函数指针和相关的参数指针。 1、栈由编译器自动分配释放空间;堆 一般由程序员分配释放。 extern “C” const void f(void); A、不做检查,和宏一样 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 在C语言中,static主要定义全局静态变量,定义局部静态变量,定义静态函数 1、全局静态变量 指针有自己的一块空间,而引用只是一个别名; 特定时间内完成特定的任务,实时性与可靠性。 左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。 1.没有回收垃圾资源 O(n^2) tcp/ip 应用层/传输层/网络层/数据链路层/物理层 ARP (Address Resolution Protocol)(地址解析协议) IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与之后才能区分哪些是网络位哪些是主机位。 switch的参数不能为实型。 能,局部会屏蔽全局。要用全局变量,需要使用"::" 可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错 可以,在不同的C文件中以static形式来声明同名全局变量。 死循环或者说无限循环。和while(1)相同。 前一个循环一遍再判断,后一个判断以后再循环 应该是4^3-1=63 设2个栈为A,B,一开始均为空. 函数名: atol c用宏定义,c++用inline #defineSECONDS_PER_YEAR (60 60 24 * 365)UL #define MIN(A,B) ((A)<= (B) (A) : (B)) 编译程序时,只要遇到 #error 就会跳出一个编译错误,既然是编译错误,要它干嘛呢?其目的就是保证程序是按照你所设想的那样进行编译的。 这个问题用几个解决方案。我首选的方案是: 这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用: 1)使用Const关键字的地方是为了说明这个参数为常量,是不应该被修改的。 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 全称Point to Point Protocol over Ethernet,意思是基于以太网的点对点协议。实质是以太网和拨号网络之间的一个中继协议,所以在网络中,它的物理结构与原来的LAN接入方式没有任何变化,只是用户需要在保持原接入方式的基础上,安装一个PPPoE客户端(这个是通用的)。之所以采用该方式给小区计时/计流量用户,是方便计算时长和流量。此类用户在使用上比包月用户增加了PPPoE虚拟拨号的过程。电信的ADSL接入也是需要安装使用PPPoE。 预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。 游标和指针 从语法上,在C中(只讨论C中)。class和struct做类型定义时只有两点区别: 最后,作为语言的两个关键字,除去定义类型时有上述区别之外,另外还有一点点:“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。 关系数据库以关系模型为基础,它有以下三部分组成: 顺序结构 层次模型、网状模型和关系模型。 工程模式即将对象创建过程封装即为工厂模式。
指针可以随时指向任意类型的内存块。
(1)修改内容上的差别
char[]=;[0]=;char*=;// 注意p 指向常量字符串[0]=;// 编译器不能发现该错误,运行时错误(2) 用运算符sizeof 可以计算出数组的容量(字节数)。sizeof§,p 为指针得到的是一个指针变量的字节数,而不是p 所指的内存容量。C++/C 语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
char[]=“hello world”;char*=;<
voidFunc(char[100]){<34、类成员函数的重载、覆盖和隐藏区别?
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)35、求出两个数中的较大者
36、如何打印出当前源文件的文件名以及源文件的当前行号?
37、main主函数执行完毕后,是否可能会再执行一段代码,给出说明?
voidmain(void){str(“zhanglin”);_onexit();_onexit();_onexit();_onexit();printf(“This is executed first.n”);}intfn1(){printf(“next.n”);return0;}intfn2(){printf("executed ");return0;}intfn3(){printf("is ");return0;}intfn4(){printf("This ");return0;}The onexit function is passed the address of a function (func) to be calledwhen the program terminates normally. Successive calls to onexit create aregister of functions that are executed in LIFO (last-in-first-out) order. Thefunctions passed to _onexit cannot take parameters.
程序正常终止时,将向onexit函数传递要调用的函数(func)的地址。 连续调用onexit会创建以LIFO(后进先出)顺序执行的功能的寄存器。 传递给_onexit的函数不能使用参数。38、如何判断一段程序是由C 编译程序还是由C++编译程序编译的?
39、文件中有一组整数,要求排序后输出到另一个文件中
#include
40、请你详细地解释一下IP协议的定义,在哪个层上面?主要有什么作用?TCP与UDP呢 ?
TCP与UDP在传输层。它提供了节点间的数据传送,应用程序之间的通信服务,主要功能是数据格式化、数据确认和丢失重传等。如传输控制协议(TCP)、用户数据报包议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。41、请问交换机和路由器各自的实现原理是什么?分别在哪个层次上面实现的?
42、全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的 ?
全局变量在数据段,而局部变量在栈,局部 变量在函数结束时内存空间就被系统收回,所以要返回的数组或字符串不要用局部变量定义.extren和在main()函数外定义的变量都称为全局变量,操 作系统和编译器从定义变量为变量分配内存时,从变量的定义和存储区域来分别局部变量和全局变量43、8086是多少位的系统?在数据总线上是怎么实现的?
代码段寄存器CS:存放当前执行的程序的段地址。
数据段寄存器DS:存放当前执行的程序所用操作数的段地址。
堆栈段寄存器SS:存放当前执行的程序所用堆栈的段地址。
附加段寄存器ES:存放当前执行程序中一个辅助数据段的段地址。
由cs:ip构成指令地址,ss:sp构成堆栈的栈顶地址指针。DS和ES用作数据段和附加段的段地址(段起始地址或段值)
8086/8088微处理器的存储器管理
段地址:偏移地址(例如,1234H:0088H)。44、解释局部变量、全局变量和静态变量的含义。
局部变量
说明:* 主函数main中定义的变量也只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效
形式参数也使局部变量
在一个函数内部,可以在复合语句中定义变量,这些变量只在本符合语句中有效* 全局变量
说明:
设全局变量的作用:增加了函数间数据联系的渠道 * a.全局变量在程序的全部执行过程中都占用存储单元;
如果外部变量在文件开头定义,则在整个文件范围内都可以使用该外部变量,如果不再文件开头定义,按上面规定作用范围只限于定义点到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在该函数中用关键字extern作外部变量说明
4.如果在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用;* 静态变量
45、论述含参数的宏与函数的优缺点。
一般来说,用宏来代表简短的表达式比较合适。
内联函数和宏很类似,而区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。
当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。
内联函数是不能为虚函数的,但样子上写成了内联的,即隐含的内联方式。在某种情况下,虽然有些函数我们声明为了所谓“内联”方式,但有时系统也会把它当作普通的函数来处理,这里的虚函数也一样,虽然同样被声明为了所谓“内联”方式,但系统会把它当然非内联的方式来处理。46、C++里面是不是所有的动作都是main()引起的?如果不是,请举例。
对于C++程序而言:
第一:静态变量、全局变量、全局对象的分配早在main()函数之前已经完成了;
第二:系统会为某个启动的程序分配地址空间,创建进程和主线程,并为main()指供参数(如果有的话),然后才转到main()执行;
第三:是C/C++的运行时启动函数:wWinMainCRTStartup 引起的,main函数也接受这个函数的调用。所以并不是所有的动作都是由main()引起的,只是编译器是由main()开始执行的,main()只不过是一个约定的函数入口,在main()函数中的显示代码执行之前,会调用一个由编译器是生成的main()函数,而main()函数会进行所有全局对象的构造及初始化工作。如:classA();;
intmain(){
//main func
}
引申:怎样在main()函数退出以后再执行一段代码?
全局变量。当程序退出时,全局变量必须销毁,自然会调用全局对象的析构函数,所以剩下的就同构造函数一样了47、如何定义和实现一个类的成员函数为回调函数?
回调函数定义
进一步解释
使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个被调用的函数。而被调用函数在需要的时候,利用传递的地址调用回调函数。
回调函数由程序员自己调用,当需要调用另一个函数时,这个函数的其中一个参数就是这个回调函数名。系统在必要的时候会调用程序员写的回调函数,这样就可以在回调函数里完成要做的事了。回调函数实现
(2)定义
(3)设置触发条件,就是在函数中把回调函数名作为一个参数,以便系统调用。
举例
typedefvoid(*)(void);//定义回调函数classA{public://回调函数,必须是声明为staticstaticvoidcallBackFun(void){…}};//设置触发条件voidFuntype(){p();}voidmain(void){Functype(:;}回调函数和API对比
相同点:
回调函数与应用程序接口(API)很相似,都是跨层调用的函数
不同点: * API是低层提供给高层的调用,一般这个函数对高层都是已知的。
48、解释堆和栈的区别。
2、栈使用的是一级缓存, 它们通常都是被调用时处于存储空间中,调用完毕立即释放;堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定。”49、C++里面如何声明const void f(void)函数为C程序中的库函数?
50、内联函数在编译时是否做参数类型检查?
B、做类型检查
C、和编译器相关
先说宏和函数的区别:
1.宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型.
2.宏的参数替换是不经计算而直接处理的,而函数调用是将实参的值传递给形参,既然说是值,自然是计算得来的.
3.宏在编译之前进行,即先用宏体替换宏名,然后再编译的,而函数显然是编译之后,在执行时,才调用的.因此,宏占用的是编译的时间,而函数占用的是执行时的时间.
4.宏的参数是不占内存空间的,因为只是做字符串的替换,而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的.
5.函数的调用是需要付出一定的时空开销的,因为系统在调用函数时,要保留现场,然后转入被调用函数去执行,调用完,再返回主调函数,此时再恢复现场,这些操作,显然在宏中是没有的.
内联函数与宏的区别:
1.内联函数在运行时可调试,而宏定义不可以;
2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会;
3.内联函数可以访问类的成员变量,宏定义则不能;
4.在类中声明同时定义的成员函数,自动转化为内联函数。
答案:B51、static有什么用途?(请至少说明两种)
答案一
在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用答案二:
一、 定义全局静态变量 :在全局变量前面加上关键字static,该全局变量变成了全局静态变量。全局静态变量有以下特点:
(1) 在全局数据区内分配内存
(2) 如果没有初始化,其默认值为0
(3) 该变量在本文件内从定义开始到文件结束可见
二、 定义局部静态变量:在局部静态变量前面加上关键字static,该局部变量便成了静态局部变量。静态局部变量有以下特点:
(1) 该变量在全局数据区分配内存
(2) 如果不显示初始化,那么将被隐式初始化为0
(3) 它始终驻留在全局数据区,直到程序运行结束
(4) 其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
三、 定义静态函数:在函数的返回类型加上static关键字,函数即被定义成静态函数。静态函数有以下特点:
(1) 静态函数只能在本源文件中使用
(2) 在文件作用域中声明的inline函数默认为static
说明:静态函数只是一个普通的全局函数,只不过受static限制,他只能在文件坐在的编译单位内使用,不能呢个在其他编译单位内使用。
在C++语言中新增了两种作用:定义静态数据成员或静态函数成员
(1) 定义静态数据成员。静态数据成员有如下特点:
(1) 内存分配:在程序的全局数据区分配
(2) 初始化和定义:静态数据成员定义时要分配空间,所以不能在类声明中定义
(3) 静态成员函数。静态成员函数与类相联系,不与类的对象相联系。静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例,主要用于对静态数据成员的操作。
(4) 静态成员函数和静态数据成员都没有this指针。答案三:
在全局变量前加上关键字static,全局变量就定义成一个全局静态变量。
静态存储区,在整个程序运行期间一直存在。
初始化:未经初始化的全局静态变量会被自动初始化为0(自动对象的值是任意的,除非他被显式初始化)。
作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。
2、局部静态变量
在局部变量之前加上关键字static,局部变量就成为一个局部静态变量。
内存中的位置:静态存储区。
初始化:未经初始化的全局静态变量会被自动初始化为0(自动对象的值是任意的,除非他被显式初始化)。
作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变。
3.、静态函数
在函数返回类型前加static,函数就定义为静态函数。函数的定义和声明在默认情况下都是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
函数的实现使用static修饰,那么这个函数只可在本cpp内使用,不会同其他cpp中的同名函数引起冲突。
warning:不要再头文件中声明static的全局函数,不要在cpp内声明非static的全局函数,如果你要在多个cpp中复用该函数,就把它的声明提到头文件里去,否则cpp内部声明需加上static修饰。
4.、类的静态成员
在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用。
5.、类的静态函数
静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。
在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);52、引用与指针有什么区别?
使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小;
指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象 的引用;
作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会改变引用所指向的对象;
可以有const指针,但是没有const引用;
指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能 被改变;
指针可以有多级指针(**p),而引用至于一级;
指针和引用使用++运算符的意义不一样;
如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。53、描述实时系统的基本特性
所谓“实时操作系统”,实际上是指操作系统工作时,其各种资源可以根据需要随时进行动态分配。由于各种资源可以进行动态分配,因此其处理事务的能力较强、速度较快。
应该说,实时操作系统是在早期的操作系统基础上发展起来的,早期的操作系统的各种资源都是事先已经分配好的,工作期间这些资源不能再重新进行分配。因此其处理事务的能力较差、速度较慢,现在则称之为“非实时操作系统”。但“非实时操作系统”诞生时,其功能、性能等在当时也是非常强的,人们在未认识到更好的操作系统之前并不将其这样称呼。将来如果新的、功能更强的、实时性能更高的操作系统出现,也许现在称之为“实时”的操作系统则可能将让位于新的“实时操作系统”了。从这方面讲“实时操作系统”是一个相对的概念的。54、全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
全局变量:全局区(静态区)(static):全局变量和静态变量是存储在一起的,初始化过的全局变量和静态变量在同一块区域,未初始化的全局变量和静态变量存放在一块相邻的区域内。此区域由系统在程序结束后释放 局部变量: 放在堆栈中。由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈
全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。 局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
静态变量分为 全局静态变量(常称为全局变量)和局部静态变量(static修饰的变量)55、什么是平衡二叉树?
56、堆栈溢出一般是由什么原因导致的?
2.层次太深的递归调用57、什么函数不能声明为虚函数?
什么样的函数不能声明为虚函数?
1)不能被继承的函数。
2)不能被重写的函数。
1.普通函数(不能被覆盖)
2.友元函数(C++不支持友元函数继承)
3.内联函数(编译期间展开,虚函数是在运行期间绑定)
4.构造函数(没有对象不能使用构造函数,先有构造函数后有虚函数,虚函数是对对象的动作)
5.静态成员函数(只有一份大家共享)
1)普通函数
普通函数不属于成员函数,是不能被继承的。普通函数只能被重载,不能被重写,因此声明为虚函数没有意义。因为编译器会在编译时绑定函数。
而多态体现在运行时绑定。通常通过基类指针指向子类对象实现多态。
2)友元函数
友元函数不属于类的成员函数,不能被继承。对于没有继承特性的函数没有虚函数的说法。
3)构造函数
首先说下什么是构造函数,构造函数是用来初始化对象的。假如子类可以继承基类构造函数,那么子类对象的构造将使用基类的构造函数,而基类构造函数并不知道子类的有什么成员,显然是不符合语义的。从另外一个角度来讲,多态是通过基类指针指向子类对象来实现多态的,在对象构造之前并没有对象产生,因此无法使用多态特性,这是矛盾的。因此构造函数不允许继承。
4)内联成员函数
我们需要知道内联函数就是为了在代码中直接展开,减少函数调用花费的代价。也就是说内联函数是在编译时展开的。而虚函数是为了实现多态,是在运行时绑定的。因此显然内联函数和多态的特性相违背。
5)静态成员函数
首先静态成员函数理论是可继承的。但是静态成员函数是编译时确定的,无法动态绑定,不支持多态,因此不能被重写,也就不能被声明为虚函数。
58、冒泡排序算法的时间复杂度是什么?
59、Internet采用哪种网络协议?该协议的主要层次结构?
60、Internet物理地址和IP地址转换采用什么协议?
61、IP地址的编码分为哪俩部分?
62、不能做switch()的参数类型是?
63、局部变量能否和全局变量重名?
局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内64、如何引用一个已经定义过的全局变量?
65、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错66、语句for( ;1 ;)有什么问题?它是什么意思?
67、do……while和while……do有什么区别?
68、static 全局变量、局部变量、函数与普通全局变量、局部变量、函数区别?
答 、全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。
从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。69、-1,2,7,28,126请问28和126中间那个数是什么?为什么?
规律是n^3-1(当n为偶数0,2,4)
n^3+1(当n为奇数1,3,5)70、用两个栈实现一个队列的功能?要求给出算法和思路!
入队:
将新元素push入栈A;
出队:
(1)判断栈B是否为空;
(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;
(3)将栈B的栈顶元素pop出;
这样实现的队列入队和出队的平摊复杂度都还是O(1), 比上面的几种方法要好。71、在c语言库函数中将一个字符转换成整型的函数是atool()吗,这个函数的原型是什么?
功 能: 把字符串转换成长整型数
用 法: long atol(const char *nptr);72、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
73、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
我在这想看到几件事情:
1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。74、写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
这个测试是为下面的目的而设的:
对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
least = MIN(*p++, b);75、预处理器标识#error的目的是什么?
76、嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
while(1){}一些程序员更喜欢如下方案:
for(;{}这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的
基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。
第三个方案是用 goto
:…goto;应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。77、关键字static的作用是什么?
在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。78、关键字const是什么含意?
2)合理使用const 可以是编译器自然的保护那些不希望被修改的参数,防止被无意的代码修改。
3)通过给优化器一些有用的信息,使用关键字const也许是代码更加紧凑。
下面的声明都是什么意思?
1)const int a;
2)int const a;
3)const int *a;
4)int * const a;
5)int const * a const;1) a是一个常整数;
2) a是一个常整数;
3) a是一个指向常整形的指针
4) a是一个指向整型的常指针;
5) a是一个指向常整型的常指针;
79、关键字volatile有什么含意 并给出三个不同的例子。
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量80、ASDL使用的是什么协议?并进行简单描述?
81、什么是预编译,何时需要预编译?
c编译系统在对程序进行通常的编译之前,先进行预处理。c提供的预处理功能主要有以下三种:1)宏定义 2)文件包含 3)条件编译
1、总是使用不经常改动的大型代码体。
2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。82、Itearator各指针的区别
我说过游标是指针,但不仅仅是指针。游标和指针很像,功能很像指针,但是实际上,游标是通过重载一元的”*”和”->”来从容器中间接地返回一个值。将这些值存储在容器中并不是一个好主意,因为每当一个新值添加到容器中或者有一个值从容器中删除,这些值就会失效。在某种程度上,游标可以看作是句柄(handle)。通常情况下游标(iterator)的类型可以有所变化,这样容器也会有几种不同方式的转变:
iterator——对于除了vector以外的其他任何容器,你可以通过这种游标在一次操作中在容器中朝向前的方向走一步。这意味着对于这种游标你只能使用“”操作符。而不能使用“–”或“+=”操作符。而对于vector这一种容器,你可以使用“+=”、“—”、“”、“-=”中的任何一种操作符和“<”、“<=”、“>”、“>=”、“==”、“!=”等比较运算符。83、C++中的class和struct的区别
(一)默认继承权限。如果不明确指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理;
(二)成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。
除了这两点,class和struct基本就是一个东西。语法上没有任何其它区别。不能因为学过C就总觉得连C中struct和class都区别很大,下面列举的说明可能比较无聊,因为struct和class本来就是基本一样的东西,无需多说。但这些说明可能有助于澄清一些常见的关于struct和class的错误认识:
(1)都可以有成员函数;包括各类构造函数,析构函数,重载的运算符,友元类,友元结构,友元函数,虚函数,纯虚函数,静态函数;
(2)都可以有一大堆public/private/protected修饰符在里边;
(3)虽然这种风格不再被提倡,但语法上二者都可以使用大括号的方式初始化:
A a = {1, 2, 3};不管A是个struct还是个class,前提是这个类/结构足够简单,比如所有的成员都是public的,所有的成员都是简单类型,没有显式声明的构造函数。
(4)都可以进行复杂的继承甚至多重继承,一个struct可以继承自一个class,反之亦可;一个struct可以同时继承5个class和5个struct,虽然这样做不太好。
(5)如果说class的设计需要注意OO的原则和风格,那么没任何理由说设计struct就不需要注意。
(6)再次说明,以上所有说法都是指在C语言中,至于在C里的情况,C里是根本没有“class”,而C的struct从根本上也只是个包装数据的语法机制。
class和struct如果定义了构造函数的话,都不能用大括号进行初始化
如果没有定义构造函数,struct可以用大括号初始化。
如果没有定义构造函数,且所有成员变量全是public的话,可以用大括号初始化。
class中默认的成员访问权限是private的,而struct中则是public的。
class继承默认是private继承,而struct继承默认是public继承。
在模版中,类型参数前面可以使用class或typename,如果使用struct,则含义不同,struct后面跟的是“non-type template parameter”,而class或typename后面跟的是类型参数。
不同点:构造函数,析构函数 this 指针84、关系模型的基本概念
●数据结构——模型所操作的对象、类型的集合
●完整性规则——保证数据有效、正确的约束条件
●数据操作——对模型对象所允许执行的操作方式
关系(Relation)是一个由行和列组成的二维表格,表中的每一行是一条记录(Record),每一列是记录的一个字段(Field)。表中的每一条记录必须是互斥的,字段的值必须具有原子性。85、C语言中结构化程序设计的三种基本控制结构
选择结构
循环结构86、三种基本的数据模型
87、设计模式:工厂模式 和 单例模式 介绍一下?
单例模式即整个类只有一个对象,并且不允许显示创建。88、const的作用有哪些,谈一谈你对const的理解?
89、描述char*、const char*、char* const、const char* const的区别?
90、指针常量和常量指针有什么区别?
91、static的作用是什么,什么情况下用到static?
92、全局变量与局部变量的区别?
93、宏定义的作用是什么?
94、内存对齐的概念?为什么会有内存对齐?
95、inline 内联函数的特点有哪些?它的优缺点是什么?
96、如何避免野指针?
97、如何计算结构体长度?
98、sizeof和strlen有什么区别?
99、知道条件变量吗?条件变量为什么要和锁配合使用?
100、如何用C 实现 C++ 的面向对象特性(封装、继承、多态)
101、memcpy怎么实现让它效率更高?
102、typedef和define有什么区别?
103、extern有什么作用,extern C有什么作用?