您的位置:首页 > 编程语言 > C语言/C++

有点难度的C++面试题

2006-11-08 21:06 302 查看
1. STL中Map内部是怎么实现的?
答:红黑树.
二叉树在平衡时或者叶子结点到根结点的高度在一定的范围内时工作起来是最有效的。红黑树算法是平衡树的一种算法。这个名字就是由于树的每个结点都被着上了红色或者黑色,结点所着的颜色被用来检测树的平衡性。在对结点插入和删除的操作中,可能会被旋转来保持树的平衡性。平均和最坏情况插入,删除,查找时间都是O(lg n)。详细内容请参考 Cormen [2001]。
理论
一个红黑树是一颗二叉查找树,具有下列的属性:
1. 所有的结点都被着色为红色或者是黑色。
2. 每一个叶子结点都是空结点,并且被着为黑色。
3. 如果父结点是红色的,那么两个子结点都是黑色的。
4. 结点到其子孙结点的每条简单路径上都包含相同数目的黑色结点。
5. 根结点永远是黑色的。

2. 对象在内存中是怎么存放的?
答:需要阅读<<Inside The C++ Object Model>>
简单说来,
在类对象的内存布局中,如果有虚函数,首先是该类的vtbl指针,然后才是对象数据,对象数据都是顺序存

放,当然会涉及到字节对齐,这样会带来存取效率的提升.

3. 说说COM的原理和实现?
答:COM,简单地说,是一种不同应用程序和不同语言来共享二进制代码的方法,不同于C++,只是源代码级的重用。Windows允许你使用DLL实现二进制级的代码共享,如kernel32.dll,user32.dll等,但因为这都是用C写的DLL,所以它们只能被C或者理解C调用方式的语言所调用。MFC引入了另一种二进制级的代码共享机制--MFC extension DLLs,但这种机制限制更多,你只能在MFC程序中使用它们。而COM通过建立一种二进制的规范来解决这些问题,这也意味着COM二进制模块要按照一种特别的结构来组织,在内存中亦然。规则是语言无关的,重担交给了编译器。

COM对象在内存中的组织结构和C++的虚函数一样,这就是为什么大多数COM代码都使用C++的原因,但记住,COM确实是语言无关的,因为生成的结果代码可以被其它所有语言所使用。顺便说,COM不是Win32规范,理论上,它能移植到Unix和其它任意的操作系统,但我没见过Windows世界以外的COM.

4. 为什么要用智能指针?是怎么实现的?
以免资源泄漏.

内部使用了引用计数机制,具体实现非常复杂.

5. 给你一个指针,并用new动态申请空间,在另一个函数中释放,不知道是申请的一个元素还是一个数组的情况下,怎么确定用delete还是delete []?
不同的编译器有不同的实现机制,比较常用的有两种:
1.new 时,在第一个对象前面记录分配了多少对象.
2.使用键值,即key-value
For ex:
int *p = new int
;
p为key,n为value.

6. 虚函数是怎么实现的?
答:简单说来使用了虚函数表.

7. 虚函数表又是怎样实现的?
答:
每个含有虚函数的类有一张虚函数表(vtbl),表中每一项指向一个虚函数的地址,实现上是一个函数指针的数组。

虚函数表既有继承性又有多态性。每个派生类的vtbl继承了它各个基类的vtbl,如果基类vtbl中包含某一项,则其派生类的vtbl中也将包含同样的一项,但是两项的值可能不同。如果派生类覆盖(override)了该项对应的虚函数,则派生类vtbl的该项指向重载后的虚函数,没有重载的话,则沿用基类的值。

在类对象的内存布局中,首先是该类的vtbl指针,然后才是对象数据。在通过对象指针调用一个虚函数时,编译器生成的代码将先获取对象类的vtbl指针,然后调用vtbl中对应的项。对于通过对象指针调用的情况,在编译期间无法确定指针指向的是基类对象还是派生类对象,或者是哪个派生类的对象。但是在运行期间执行到调用语句时,这一点已经确定,编译后的调用代码能够根据具体对象获取正确的vtbl,调用正确的虚函数,从而实现多态性。

分析一下这里的思想所在,问题的实质是这样,对于发出虚函数调用的这个对象指针,在编译期间缺乏更多的信息,而在运行期间具备足够的信息,但那时已不再进行绑定了,怎么在二者之间作一个过渡呢?把绑定所需的信息用一种通用的数据结构记录下来,该数据结构可以同对象指针相联系,在编译时只需要使用这个数据结构进行抽象的绑定,而在运行期间将会得到真正的绑定。这个数据结构就是vtbl。可以看到,实现用户所需的抽象和多态需要进行后绑定,而编译器又是通过抽象和多态而实现后绑定的.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: