首页 » 网站推广 » mfc与php交互技巧_linux CC做事器后台开拓面试题总结编程措辞篇

mfc与php交互技巧_linux CC做事器后台开拓面试题总结编程措辞篇

访客 2024-12-15 0

扫一扫用手机浏览

文章目录 [+]

1.根据熟习的措辞,谈谈两种措辞的差异?

紧张浅谈下C/C++和PHP措辞的差异:

mfc与php交互技巧_linux CC做事器后台开拓面试题总结编程措辞篇

1)PHP弱类型措辞,一种脚本措辞,对数据的类型不哀求过多,较多的运用于Web运用开拓,现在好多互联网开拓公司的主流web后台开拓措辞,紧张框架为mvc模型,如smarty,yaf,升级的PHP7速率较快,对做事器的压力要小很多,在新浪微博已经有运用,比拟很明显。

mfc与php交互技巧_linux CC做事器后台开拓面试题总结编程措辞篇
(图片来自网络侵删)

2)C/C++开拓措辞,C措辞更倾向硬件底层开拓,C++措辞是目前为止我认为语法内容最多的一种措辞。
C/C++在实行速率上要快很多,毕竟其他类型的措辞大都是C开拓的,更多运用于网络编程和嵌入式编程。

2.volatile是干啥用的,(必须将cpu的寄存器缓存机制回答的很透彻),利用实例有哪些?(重点)

1)访问寄存器比访问内存单元要快,编译器会优化减少内存的读取,可能会读脏数据。
声明变量为volatile,编译器不再对访问该变量的代码优化,仍旧从内存读取,使访问稳定。

总结:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变革,与该变量有关的运算,不再编译优化,以免出错。

2)利用实例如下(区分C程序员和嵌入式系统程序员的最基本的问题。
):

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

一个中断做事子程序中会访问到的非自动变量(Non-automatic variables)

多线程运用中被几个任务共享的变量

3)一个参数既可以是const还可以是volatile吗?阐明为什么。

可以。
一个例子是只读的状态寄存器。
它是volatile由于它可能被意想不到地改变。
它是const由于程序不应该试图去修正它。

4)一个指针可以是volatile 吗?阐明为什么。

可以。
只管这并不很常见。
一个例子当中断做事子程序修该一个指向一个buffer的指针时。

下面的函数有什么缺点:

int square(volatile int ptr) {return ptr ptr;}

下面是答案:

这段代码有点变态。
这段代码的目的是用来返指针ptr指向值的平方,但是,由于ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int ptr){int a,b;a = ptr;b = ptr;return a b;}

由于ptr的值可能被意想不到地该变,因此a和b可能是不同的。
结果,这段代码可能返不是你所期望的平方值!
精确的代码如下:

long square(volatile int ptr){int a;a = ptr;return a a;}

3.static const等等的用法,(能说出越多越好)(重点)

² 首先说说const的用法(绝对不能说是常数)

1)在定义的时候必须进行初始化

2)指针可以是const 指针,也可以是指向const工具的指针

3)定义为const的形参,即在函数内部是不能被修正的

4)类的成员函数可以被声明为常成员函数,不能修正类的成员变量

5)类的成员函数可以返回的是常工具,即被const声明的工具

6)类的成员变量是常成员变量不能在声明时初始化,必须在布局函数的列表里进行初始化

(注:千万不要说const是个常数,会被认为是外行人的!



哪怕说个只读也行)

下面的声明都是什么意思?

const int a; a是一个常整型数

int const a; a是一个常整型数

const int a; a是一个指向常整型数的指针,整型数是不可修正的,但指针可以

int const a; a为指向整型数的常指针,指针指向的整型数可以修正,但指针是不可修正的

int const a const; a是一个指向常整型数的常指针,指针指向的整型数是不可修正的,同时指针也是不可修正的

通过给优化器一些附加的信息,利用关键字const大概能产生更紧凑的代码。
合理地利用关键字const可以使编译器很自然地保护那些不肯望被改变的参数,防止其被无意的代码修正。
简而言之,这样可以减少bug的涌现。

Const如何做到只读?

这些在编译期间完成,对付内置类型,如int, 编译器可能利用常数直接更换掉对此变量的引用。
而对付构造体不一定。

c/c++linux后台开拓技能学习视频,后台私信【视频】获取

² 再说说static的用法(三个明显的浸染一定要答出来)

1)在函数体,一个被声明为静态的变量在这一函数被调用过程中坚持其值不变。

2)在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。
它是一个本地的全局变量。

3)在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。
那便是,这个函数被限定在声明它的模块确当地范围内利用

4)类内的static成员变量属于全体类所拥有,不能在类内进行定义,只能在类的浸染域内进行定义

5)类内的static成员函数属于全体类所拥有,不能包含this指针,只能调用static成员函数

static全局变量与普通的全局变量有什么差异?static局部变量和普通局部变量有什么差异?static函数与普通函数有什么差异?

static全局变量与普通的全局变量有什么差异:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么差异:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么差异:static函数在内存中只有一份,普通函数在每个被调用中坚持一份拷贝

4.extern c 浸染

见告编译器该段代码以C措辞进行编译。

5.指针和引用的差异

1)引用是直接访问,指针是间接访问。

2)引用是变量的别名,本身不单独分配自己的内存空间,而指针有自己的内存空间

3)引用绑定内存空间(必须赋初值),是一个变量别名不能变动绑定,可以改变工具的值。

总的来说:引用既具有指针的效率,又具有变量利用的方便性和直不雅观性

6. 关于静态内存分配和动态内存分配的差异及过程

1) 静态内存分配是在编译时完成的,不占用CPU资源;动态分配内存运行时完成,分配与开释须要占用CPU资源;

2)静态内存分配是在栈上分配的,动态内存是堆上分配的;

3)动态内存分配须要指针或引用数据类型的支持,而静态内存分配不须要;

4)静态内存分配是按操持分配,在编译前确定内存块的大小,动态内存分配运行时按需分配。

5)静态分配内存是把内存的掌握权交给了编译器,动态内存把内存的掌握权交给了程序员;

6)静态分配内存的运行效率要比动态分配内存的效率要高,由于动态内存分配与开释须要额外的开销;动态内存管理水平严重依赖于程序员的水平,处理不当随意马虎造成内存泄露。

7. 头文件中的 ifndef/define/endif 干什么用?

预处理,防止头文件被重复利用,包括pragma once都是这样的

8. 宏定义求两个元素的最小值

#define MIN(A,B) ((A) <= (B) ? (A) : (B))

9. 分别设置和打消一个整数的第三位?

#define BIT3 (0x1<<3)static int a;void set_bit3(void){ a |= BIT3;} void clear_bit3(void){ a &= ~BIT3;}

10. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒

#define SECONDS_PER_YEAR (60 60 24 365)UL

11. 预处理器标识#error的目的是什么?

抛出错误提示,标识外部宏是否被定义!

12. 嵌入式系统中常常要用到无限循环,你怎么样用C编写去世循环呢?

记住这是第一方案!



while(1)

{

}

一些程序员更喜好如下方案:

for(;;){

}

汇编措辞的无线循环是:

Loop:

...

goto Loop;

13. 用变量a给出下面的定义

一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数 int (a[10])(int);

14. 中断是嵌入式系统中主要的组成部分,这导致了很多编译开拓商供应一种扩展—让标准C支持中断。
具代表事实是,产生了一个新的关键字 __interrupt

16. memcpy函数的实现

void memcpy(void dest, const void src, size_t count) { char tmp = dest; const char s = src; while (count--) tmp++ = s++; return dest;}

17. Strcpy函数实现

char strcpy(char dst,const char src) { assert(dst != NULL && src != NULL); char ret = dst; while(( dst++ = src++) != '\0') ; return ret; }

18. strcat函数的实现

char strcat(char strDes, const char strSrc){assert((strDes != NULL) && (strSrc != NULL));char address = strDes;while (strDes != ‘\0′)++ strDes;while ((strDes ++ = strSrc ++) != ‘\0′)return address;}

19.strncat实现

char strncat(char strDes, const char strSrc, int count){assert((strDes != NULL) && (strSrc != NULL));char address = strDes;while (strDes != ‘\0′)++ strDes;while (count — && strSrc != ‘\0′ )strDes ++ = strSrc ++;strDes = ‘\0′;return address;}

20. strcmp函数实现

int strcmp(const char str1,const char str2){ /不可用while(str1++==str2++)来比较,当不相等时仍会实行一次++, return返回的比较值实际上是下一个字符。
应将++放到循环体中进行。
/ while(str1 == str2){ if(str1 == '\0') return0; ++str1; ++str2; } return str1 - str2;}

21. strncmp实现

int strncmp(const char s, const char t, int count){

assert((s != NULL) && (t != NULL));

while (s && t && s == t && count –) {

++ s;

++ t;

}

return (s – t);

}

22.strlen函数实现

int strlen(const char str){ assert(str != NULL); int len = 0; while (str ++ != ‘\0′) ++ len; return len;}

23. strpbrk函数实现

char strpbrk(const char cs,const char ct){ const char sc1,sc2; for( sc1 = cs; sc1 != '\0'; ++sc1){ for( sc2 = ct; sc2 != '\0'; ++sc2){ if (sc1 == sc2){ return (char ) sc1; } } } return NULL;}

24. strstr函数实现

char strstr(const char s1,const char s2){int len2;if(!(len2=strlen(s2)))//此种情形下s2不能指向空,否则strlen无法测出长度,这条语句缺点return(char)s1;for(;s1;++s1){ if(s1==s2 && strncmp(s1,s2,len2)==0) return(char)s1;}return NULL;}

25. string实现(把稳:赋值布局,operator=是关键)

class String{public://普通布局函数String(const char str = NULL);//拷贝布局函数String(const String &other);//赋值函数String & operator=(String &other) ;//析构函数~String(void);private:char m_str;};

分别实现以上四个函数

//普通布局函数String::String(const char str){ if(str==NULL) //如果str为NULL,存空字符串{ m_str = new char[1]; //分配一个字节 m_str = ‘\0′; //赋一个’\0′}else{ str = new char[strlen(str) + 1];//分配空间容纳str内容 strcpy(m_str, str); //复制str到私有成员m_str中 }} //析构函数String::~String(){ if(m_str!=NULL) //如果m_str不为NULL,开释堆内存{ delete [] m_str; m_str = NULL;}} //拷贝布局函数String::String(const String &other){ m_str = new char[strlen(other.m_str)+1]; //分配空间容纳str内容 strcpy(m_str, other.m_str); //复制other.m_str到私有成员m_str中 } //赋值函数String & String::operator=(String &other){ if(this == &other) //若工具与other是同一个工具,直接返回本{ return this} delete [] m_str; //否则,先开释当前工具堆内存 m_str = new char[strlen(other.m_str)+1]; //分配空间容纳str内容 strcpy(m_str, other.m_str); //复制other.m_str到私有成员m_str中 return this;}

26. C措辞赞许一些令人震荡的构造,下面的构造是合法的吗,如果是它做些什么?

int a = 5, b = 7, c;

c = a+++b; 等同于 c = a++ + b;

因此, 这段代码持行后a = 6, b = 7, c = 12。

27. 用struct关键字与class关键定义类以及继续的差异

(1)定义类差别

struct关键字也可以实现类,用class和struct关键字定义类的唯一差别在于默认访问级别:默认情形下,struct成员的访问级别为public,而class成员的为private。
语法利用也相同,直接将class改为struct即可。

(2)继续差别

利用class保留字的派生类默认具有private继续,而用struct保留字定义的类某人具有public继续。
其它则没有任何差异。

紧张点就两个:默认的访问级别和默认的继续级别 class都是private

28.派生类与虚函数概述

(1) 派生类继续的函数不能定义为虚函数。
虚函数是希望派生类重新定义。
如果派生类没有重新定义某个虚函数,则在调用的时候会利用基类中定义的版本。

(2)派生类中函数的声明必须与基类中定义的办法完备匹配。

(3) 基类中声明为虚函数,则派生类也为虚函数。

29. 虚函数与纯虚函数差异

1)虚函数在子类里面也可以不重载的;但纯虚必须在子类去实现

2)带纯虚函数的类叫虚基类也叫抽象类,这种基类不能直接天生工具,只能被继续,重写虚函数后才能利用,运行时动态动态绑定!

30.深拷贝与浅拷贝

浅拷贝:

char ori[]=“hello”;char copy=ori;

深拷贝:

char ori[]=\"大众hello\公众; char copy=new char[]; copy=ori;

浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

浅拷贝可能涌现的问题:

1) 浅拷贝只是拷贝了指针,使得两个指针指向同一个地址,这样在工具块结束,调用函数析构的时,会造成同一份资源析构2次,即delete同一块内存2次,造成程序崩溃。

2) 浅拷贝使得两个指针都指向同一块内存,任何一方的变动都会影响到另一方。

3) 同一个空间,第二次开释失落败,导致无法操作该空间,造成内存泄露。

31. stl各容器的实现事理(必考)

1) Vector顺序容器,是一个动态数组,支持随机插入、删除、查找等操作,在内存中是一块连续的空间。
在原有空间不足情形下自动分配空间,增加为原来的两倍。
vector随机存取效率高,但是在vector插入元素,须要移动的数目多,效率低下。

注:vector动态增加大小时因此原大小的两倍其余配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后布局新元素,并开释原空间。
因此,对vector空间重新配置,指向原vector的所有迭代器就都失落效了。

2) Map关联容器,以键值对的形式进行存储,方便进行查找。
关键词起到索引的浸染,值则表示与索引干系联的数据。
红黑树的构造实现,插入删除等操作都在O(logn)韶光内完成。

3) Set是关联容器,set每个元素只包含一个关键字。
set支持高效的关键字检讨是否在set中。
set也因此红黑树的构造实现,支持高效插入、删除等操作。

32.哪些库函数属于高危函数,为什么?

strcpy 赋值到目标区间可能会造成缓冲区溢出!

33.STL有7种紧张容器:vector,list,deque,map,multimap,set,multiset

34.你如何理解MVC。
大略举例来解释其运用。

MVC模式是observer 模式的一个特例,现在很多都是java的一些框架,MFC的,PHP的。

35.C++特点是什么,多态实现机制?(口试问过)多态浸染?两个必要条件?

C++中多态机制紧张表示在两个方面,一个是函数的重载,一个是接口的重写。
接口多态指的是“一个接口多种形态”。
每一个工具内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。
以是在程序中,不管你的工具类型如何转换,但该工具内部的虚表指针是固定的,以是呢,才能实现动态的工具函数调用,这便是C++多态性实现的事理。

多态的根本是继续,须要虚函数的支持,大略的多态是很大略的。
子类继续父类大部分的资源,不能继续的有布局函数,析构函数,拷贝布局函数,operator=函数,友元函数等等

浸染:

隐蔽实现细节,代码能够模块化;2. 接口重用:为了类在继续和派生的时候精确调用。

必要条件:

1. 一个基类的指针或者引用指向派生类的工具;2.虚函数

36. 多重继续有什么问题? 若何肃清多重继续中的二义性?

1)增加程序的繁芜度,使程序的编写和掩护比较困难,随意马虎出错;

2)继续类和基类的同名函数产生了二义性,同名函数不知道调用基类还是继续类,C++中利用虚函数办理这个问题

3)继续过程中可能会继续一些不必要的数据,对付多级继续,可能会产生数据很长

可以利用成员限定符和虚函数办理多重继续中函数的二义性问题。

37.求两个数的乘积和商数,该浸染由宏定义来实现

#define product(a,b) ((a)(b))

#define divide(a,b) ((a)/(b))

38.什么叫静态关联,什么叫动态关联

多态中,静态关联是程序在编译阶段就能确定实际实行动作,程序运行才能确定叫动态关联

39.什么叫智能指针?常用的智能指针有哪些?智能指针的实现?

智能指针是一个存储指向动态分配(堆)工具指针的类,布局函数传入普通指针,析构函数开释指针。
栈上分配,函数或程序结束自动开释,防止内存透露。
利用引用计数器,类与指向的工具干系联,引用计数跟踪该类有多少个工具共享同一指针。
创建类的新工具时,初始化指针并将引用计数置为1;当工具作为另一工具的副本而创建,增加引用计数;对一个工具进行赋值时,减少引用计数,并增加右操作数所指工具的引用计数;调用析构函数时,布局函数减少引用计数,当引用计数减至0,则删除根本工具。

std::auto_ptr,不支持复制(拷贝布局函数)和赋值(operator =),编译不会提示出错。

C++11引入的unique_ptr, 也不支持复制和赋值,但比auto_ptr好,直接赋值会编译出错。

C++11或boost的shared_ptr,基于引用计数的智能指针。
可随意赋值,直到内存的引用计数为0的时候这个内存会被开释。
还有Weak_ptr

40.列举与#define 宏的差异

1)#define 宏常量是在预编译阶段进行大略更换。
列举常量则是在编译的时候确定其值。

2)可以调试列举常量,但是不能调试宏常量。

3)列举可以一次定义大量干系的常量,而#define 宏一次只能定义一个。

41.先容一下函数的重载

重载是在不同类型上作不同运算而又用同样的名字的函数。
重载函数至少在参数个数,参数类型, 或参数顺序上有所不同。

42.派生新类的过程要经历三个步骤

1.接管基类成员 2.改造基类成员 3.添加新成员

43.面向工具的三个基本特色,并大略阐述之?

1)封装:将客不雅观事物抽象成类,每个类对自身的数据和方法实施2)继续3)多态:许可一个基类的指针或引用指向一个派生类工具

44.多态性表示都有哪些?动态绑定怎么实现?

多态性是一个接口,多种实现,是面向工具的核心。
编译时多态性:通过重载函数实现。
运行时多态性:通过虚函数实现,结合动态绑定。

45.虚函数,虚函数表里面内存如何分配?

编译时若基类中有虚函数,编译器为该的类创建一个一维数组的虚表,存放是每个虚函数的地址。
基类和派生类都包含虚函数时,这两个类都建立一个虚表。
布局函数中进行虚表的创建和虚表指针的初始化。
在布局子类工具时,要先调用父类的布局函数,初始化父类工具的虚表指针,该虚表指针指向父类的虚表。
实行子类的布局函数时,子类工具的虚表指针被初始化,指向自身的虚表。
每一个类都有虚表。
虚表可以继续,如果子类没有重写虚函数,那么子类虚表中仍旧会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。
派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。
当用一个指针/引用调用一个函数的时候,被调用的函数是取决于这个指针/引用的类型。
即如果这个指针/引用是基类工具的指针/引用就调用基类的方法;如果指针/引用是派生类工具的指针/引用就调用派生类的方法,当然如果派生类中没有此方法,就会向上到基类里面去探求相应的方法。
这些调用在编译阶段就确定了。
当涉及到多态性的时候,采取了虚函数和动态绑定,此时的调用就不会在编译时候确定而是在运行时确定。
不在单独考虑指针/引用的类型而是看指针/引用的工具的类型来判断函数的调用,根据工具中虚指针指向的虚表中的函数的地址来确定调用哪个函数。

46. 纯虚函数如何定义?含有纯虚函数的类称为什么?为什么析构函数要定义成虚函数?

纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但哀求任何派生类都要定义自己的实现方法。
纯虚函数是虚函数再加上= 0。
virtual void fun ()=0。
含有纯虚函数的类称为抽象类在很多情形下,基类本身天生工具是不合情理的。
例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身天生工具明显不合常理。
同时含有纯虚拟函数的类称为抽象类,它不能天生工具。
如果析构函数不是虚函数,那么开释内存时候,编译器会利用静态联编,认为p便是一个基类指针,调用基类析构函数,这样子类工具的内存没有开释,造成内存泄露。
定义成虚函数往后,就会动态联编,先调用子类析构函数,再基类。

47. C++中哪些不能是虚函数?

1)普通函数只能重载,不能被重写,因此编译器会在编译时绑定函数。

2)布局函数是知道全部信息才能创建工具,然而虚函数许可只知道部分信息。

3)内联函数在编译时被展开,虚函数在运行时才能动态绑定函数。

4)友元函数 由于不可以被继续。

5)静态成员函数 只有一个实体,不能被继续。
父类和子类共有。

48. 类型转换有哪些?各适用什么环境?dynamic_cast转换失落败时,会涌现什么情形(对指针,返回NULL.对引用,抛出bad_cast非常)?

静态类型转换,static_cast,基本类型之间和具有继续关系的类型。

例子A,double类型转换成int。
B,将子类工具转换成基类工具。

常量类型转换,const_cast, 去除指针变量的常量属性。

无法将非指针的常量转换为普通变量。

动态类型转换,dynamic_cast,运行时进行转换剖析的,并非在编译时进行。
dynamic_cast转换符只能用于含有虚函数的类。
dynamic_cast用于类层次间的向上转换和向下转换,还可以用于类间的交叉转换。
在类层次间进行向上转换,即子类转换为父类,此时完成的功能和static_cast是相同的,由于编译器默认向上转换总是安全的。
向下转换时,dynamic_cast具有类型检讨的功能,更加安全。
类间的交叉转换指的是子类的多个父类之间指针或引用的转换。
该函数只能在继续类工具的指针之间或引用之间进行类型转换,或者有虚函数的类。

49. 如何判断一段程序是由C 编译程序还是由C++编译程序编译的?

#ifdef __cpluspluscout<<\公众C++\"大众;#elsecout<<\公众c\"大众;#endif

50. 为什么要用static_cast转换而不用c措辞中的转换?

Static_cast转换,它会检讨类型看是否能转换,有类型安全检讨。

比如,这个在C++中合法,但是确实缺点的。

A a= new A;

B b = (B)a;

51. 操作符重载(+操作符),详细如何去定义?

除了类属关系运算符”.”、成员指针运算符”.”、浸染域运算符”::”、sizeof运算符和三目运算符”?:”以外,C++中的所有运算符都可以重载。

<返回类型解释符> operator <运算符符号>(<参数表>){}

重载为类的成员函数和重载为类的非成员函数。
参数个数会不同,应为this指针。

52. 内存对齐的原则?

A.构造体的大小为最大成员的整数倍。

B.成员首地址的偏移量为其类型大小整数倍。

53. 内联函数与宏定义的差异?

内联函数是用来肃清函数调用时的韶光开销。
频繁被调用的短小函数非常受益。

A. 宏定义不检讨函数参数,返回值什么的,只是展开,相对来说,内联函数会检讨参数类型,以是更安全。

B. 宏是由预处理器对宏进行替代,而内联函数是通过编译器掌握来实现的

54. 动态分配工具和静态分配工具的差异?

动态分配便是用运算符new来创建一个类的工具,在堆上分配内存。

静态分配便是A a;这样来由编译器来创建一个工具,在栈上分配内存。

55. explicit是干什么用的 ?

布局器 ,可以阻挡不应该许可的经由转换布局函数进行的隐式转换的发生。
explicit是用来防止外部非正规的拷贝布局的,要想不存在传值的隐式转换问题。

56. 内存溢出有那些成分?

(1) 利用非类型安全(non-type-safe)的措辞如 C/C++ 等。

(2) 以不可靠的办法存取或者复制内存缓冲区。

(3) 编译器设置的内存缓冲区太靠近关键数据构造。

57. new与malloc的差异,delete和free的差异?

1.malloc/free是C/C++措辞的标准库函数,new/delete是C++的运算符

2.new能够自动分配空间大小,malloc传入参数。

3. new/delete能进行对工具进行布局和析构函数的调用进而对内存进行更加详细的事情,而malloc/free不能。

既然new/delete的功能完备覆盖了malloc/free,为什么C++还保留malloc/free呢?由于C++程序常常要调用C函数,而C程序只能用malloc/free管理动态内存。

58. 必须利用初始化列表初始化数据成员的情形

1.是工具的情形;

2.const润色的类成员;

3.引用成员数据;

类成员变量的初始化不是按照初始化表顺序被初始化,是按照在类中声明的顺序被初始化的。

59.深入谈谈堆和栈

1).分配和管理办法不同 :

堆是动态分配的,其空间的分配和开释都由程序员掌握。

栈由编译器自动管理。
栈有两种分配办法:静态分配和动态分配。
静态分配由编译器完成,比如局部变量的分配。
动态分配由alloca()函数进行分配,但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行开释,无须手工掌握。

2).产生碎片不同

对堆来说,频繁的new/delete或者malloc/free势必会造成内存空间的不连续,造成大量的碎片,使程序效率降落。

对栈而言,则不存在碎片问题,由于栈是前辈后出的行列步队,永久不可能有一个内存块从栈中间弹出。

3).成长方向不同

堆是向着内存地址增加的方向增长的,从内存的低地址向高地址方向增长。

栈是向着内存地址减小的方向增长,由内存的高地址向低地址方向增长。

60.内存的静态分配和动态分配的差异?

韶光不同。
静态分配发生在程序编译和连接时。
动态分配则发生在程序调入和实行时。

空间不同。
堆都是动态分配的,没有静态分配的堆。
栈有2种分配办法:静态分配和动态分配。
静态分配是编译器完成的,比如局部变量的分配。
alloca,可以从栈里动态分配内存,不用担心内存透露问题,当函数返回时,通过alloca申请的内存就会被自动开释掉。

61. 模版怎么实现?模版浸染?

实现:template void swap(T& a, T& b){}

浸染:将算法与详细工具分离,与类型无关,通用,节省精力

62. 多重类布局和析构的顺序

记住析构函数的调用顺序与布局函数是相反的。

63. 迭代器删除元素的会发生什么?

迭代器失落效

64. 静态成员函数和数据成员有什么意义?

1)非静态数据成员,每个工具都有自己的拷贝。
而静态数据成员被当作是类的成员,是该类的所有工具所共有的,在程序中只分配一次内存只有一份拷贝,以是工具都共享,值对每个工具都是一样的,它的值可以更新。

2)静态数据成员存储在全局数据区,以是不能在类声明中定义,该当在类外定义。
由于它不属于特定的类工具,在没有产生类工具时浸染域就可见,即在没有产生类的实例时,我们就可以操作它。

3)静态成员函数与静态数据成员一样,都是在类的内部实现,属于类定义的一部分。
由于普通成员函数总是详细的属于详细工具的,每个有this指针。
静态成员函数没有this指针,它无法访问属于类工具的非静态数据成员,也无法访问非静态成员函数。
静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;

4)非静态成员函数可以任意地访问静态成员函数和静态数据成员;

5)没有this指针的额外开销,静态成员函数与类的全局函数比较,速率上会有少许的增长;

6)调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的工具或指向类工具的指调用静态成员函数。

65.sizeof一个类求大小(把稳成员变量,函数,虚函数,继续等等对大小的影响)

http://blog.csdn.net/jollyhope/article/details/1895357

http://www.cnblogs.com/BeyondTechnology/archive/2010/09/21/1832369.html

66请用C/C++实现字符串反转(不调用库函数)”abc”类型的

char reverse_str(char str) { if(NULL == str) { //字符串为空直接返回 return str; } char begin; char end; begin = end = str; while(end != '\0') { //end指向字符串的末端 end++; } --end; char temp; while(begin < end) { //交流两个字符 temp = begin; begin = end; end = temp; begin++; end--; } return str; //返回结果}

67.写一个函数,将字符串翻转,翻转办法如下:“I am a student”反转成“student a am I”,不借助任何库函数

1 #include \公众stdio.h\"大众 2 #include <iostream> 3 using namespace std; 4 5 void revesal(char start, char end){ 6 char temp_s = start; 7 char temp_e = end; 8 while(temp_s < temp_e){ 9 char temp= temp_s; 10 temp_s= temp_e; 11 temp_e = temp; 12 ++temp_s; 13 --temp_e; 14 } 15 return; 16 } 17 18 void revesal_str(char str){ 19 if(str == NULL){ 20 return; 21 } 22 23 char start = str; 24 char end = str; 25 26 while(++end !='\0'); 27 revesal(start, end-1); 28 cout << str << endl; 29 char sub_start = str; 30 while(start < end + 1 ){ 31 if(start == ' ' || start == '\0'){ 32 char temp = start - 1; 33 revesal(sub_start,temp); 34 while(++start ==' '); 35 sub_start = start; 36 continue; 37 } 38 ++start; 39 } 40 }

68.析构函数可以抛出非常吗?为什么不能抛出非常?除了资源透露,还有其他需考虑的成分吗?

C++标准指明析构函数不能、也不应该抛出非常。
C++非常处理模型最大的特点和上风便是对C++中的面向工具供应了最强大的无缝支持。
那么如果工具在运行期间涌现了非常,C++非常处理模型有任务打消那些由于涌现非常所导致的已经失落效了的工具(也即工具超出了它原来的浸染域),并开释工具原来所分配的资源, 这便是调用这些工具的析构函数来完成开释资源的任务,以是从这个意义上说,析构函数已经变成了非常处理的一部分。

1)如果析构函数抛出非常,则非常点之后的程序不会实行,如果析构函数在非常点之后实行了某些必要的动作比如开释某些资源,则这些动作不会实行,会造成诸如资源泄露的问题。

2)常日非常发生时,c++的机制会调用已经布局工具的析构函数来开释资源,此时若析构函数本身也抛出非常,则前一个非常尚未处理,又有新的非常,会造成程序崩溃的问题。

69. 拷贝布局函数浸染及用场?什么时候须要自定义拷贝布局函数?

一样平常如果布局函数中存在动态内存分配,则必须定义拷贝布局函数。
否则,可能会导致两个工具成员指向同一地址,涌现“指针悬挂问题”。

70. 100万个32位整数,如何最快找到中位数。
能担保每个数是唯一的,如何实现O(N)算法?

1).内存足够时:快排

2).内存不敷时:分桶法:化大为小,把所有数划分到各个小区间,把每个数映射到对应的区间里,对每个区间中数的个数进行计数,数一遍各个区间,看看中位数落在哪个区间,若够小,利用基于内存的算法,否则 连续划分

71. OFFSETOF(s, m)的宏定义,s是构造类型,m是s的成员,求m在s中的偏移量。

#define OFFSETOF(s, m) size_t(&((s)0)->m)

72. C++虚函数是如何实现的?

利用虚函数表。
C++工具利用虚表, 如果是基类的实例,对应位置存放的是基类的函数指针;如果是继续类,对应位置存放的是继续类的函数指针(如果在继续类有实现)。
以是 ,当利用基类指针调用工具方法时,也会根据详细的实例,调用到继续类的方法。

73. C++的虚函数有什么浸染?

虚函数浸染是实现多态,虚函数实在是实现封装,使得利用者不须要关心实现的细节。
在很多设计模式中都是这样用法,例如Factory、Bridge、Strategy模式。

74.MFC中CString是类型安全类吗,为什么?

不是,其他数据类型转换到CString可以利用CString的成员函数Format来转换

74.动态链接库的两种利用方法及特点?

1).载入时动态链接,模块非常明确调用某个导出函数,使得他们就像本地函数一样。
这须要链接时链接那些函数所在DLL的导入库,导入库向系统供应了载入DLL时所需的信息及DLL函数定位。

2)运行时动态链接。

标签:

相关文章