1. 以下程序的输出结果为 ( )
1 #include <iostream> 2 3 main( ) 4 5 { 6 7 using namespace std; 8 9 int num[5]={1,2,3,4,5}; 10 11 cout <<*((int *)(&num+1)-1) <<endl; 12 13 }
A. 1 B.2 C. 3 D. 4 E. 5 F. 0 G. 未初始化内存,无法确定
在C语言中,一维数组名表示数组的首地址,而且是一个指针.如上例num,
对&num,表示指针的指针.意味着这里强制转换为二维数组指针.
这样 &num+1 等同于 num[5][1],为代码空间. (&num+1)-1表示 num[4][0].即num[4].所以这里答案是E.
2.
1 class a 2 3 { 4 5 public: 6 7 virtual void funa( ); 8 9 virtual void funb( ); 10 11 void fun( ); 12 13 static void fund( ); 14 15 static int si; 16 17 private: 18 19 int i; 20 21 char c; 22 23 };
问: 在32位编译器默认情况下,sizeof(a)等于( )字节?
A. 28 B. 25 C.24 D. 20 E. 16 F.12 G. 8
答案在VC++下是 12. 这里需要考虑三个问题,一是虚函数表vtable的入口表地址,二是字节对齐.三 ,静态成员是所有对象共享,不计入sizeof空间.
在大部分C++的实现中,带有虚函数的类的前4个BYTE是虚函数vtable表的这个类入口地址.所以sizeof必须要加入这个4个byte的长度,除此外,类的sizoef()为所有数据成员总的sizeof之和,这里是int i,和char c.其中char c被字节对齐为4.这样总长度为
Sizeof(a) = sizeof(vtable)+size(int)+sizeof(char + pad) = 12;
3. 如下程序:
1 int i=1,k=0; 2 3 long *pl=NULL; 4 5 char *pc=NULL; 6 7 if(k++&&i++) 8 9 k++, pl++, pc++; 10 11 if(i++||k++) 12 13 i++, pl++, pc++; 14 15 printf(“i=%d,k=%d,pl=%ld,pc=%ld\n”,i,k,(long)pl,(long)pc);
打印结果为__i=3,k=1,pl=4,pc=1________
主要测试逻辑表达式的短路操作.
&&操作中,前一个表达式为0,后一表达式不执行
||操作中, 前一个表达式为1,后一表达式不执行
4. 以下程序的输出为______________
1 #include<iostream> 2 using std::cout; 3 class A 4 { 5 public: 6 void f(void){ 7 cout<< ”A::f” <<’ ‘; 8 } 9 10 virtual void g(void) 11 { 12 cout <<”A::g” << ‘ ‘; 13 } 14 }; 15 16 17 class B : public A 18 { 19 20 public: 21 void f(void) 22 { 23 cout << “B :: f “ << ‘ ‘; 24 } 25 26 void g(void) 27 { 28 cout << “B:: g “ << ‘ ‘; 29 } 30 }; 31 32 33 int main() 34 { 35 A* pA =new B; 36 pA->f(); 37 pA->g(); 38 B* pB = (B*)pA; 39 pB->f(); 40 pB->g(); 41 42 }
多态中虚函数调用.
f()为非虚函数,这样强制转换后,执行本类的同名函数.
G()为虚函数,指针总是执行虚函数,这就是多态..
5. 以下为window NT 下32 位C++程序,请填写如下值
1 class myclass 2 3 { 4 5 int a ; 6 7 int b; 8 9 }; 10 11 char *p = “hello”; 12 13 char str[] = “world”; 14 15 myclass classes[2]; 16 17 void *p2= malloc(100);
sizeof(p)=_4__
sizeof(str)=_6_
sizeof(classes)=_16__
sizeof(p2)=_4___
6. 在程序设计中,对公共资源(比如缓冲区等)的操作和访问经常需要使用锁来进行保护,但在大并发系统中过多的锁会导致效率很低,通常有那些方法可以尽量避免或减少锁的使用?
减少锁的粒度,每次尽可能减少锁范围
采用队列处理,这样无需使用锁.
7. 请详细阐述如何在release版本(windows程序或linux程序都可以)中,查找段错误问题.
可以用编译器生成map文件来定位源码.通过地址反查源码
8.在编写C++赋值运算符时有哪些要注意的地方?
返回值,参数最好用引用
减少友元函数使用,移植有问题.
9.请指出spinlock,mutex,semaphore,critical section的作用与区别,都在哪些场合使用.
spin_lock Linux 内核自旋锁. Mutex Windows 互质量, semaphore POSIX ,critical section Windows
10.什么是“引用”?申明和使用“引用”要注意哪些问题?
答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完
毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引
用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。
11. 在什么时候需要使用“常引用”?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;
例1
1 int a ; 2 const int &ra=a; 3 ra=1; //错误 4 a=1; //正确
例2
1 string foo( ); 2 void bar(string & s); 3 4 //那么下面的表达式将是非法的: 5 6 bar(foo( )); 7 bar(“hello world”);
原因在于foo( )和”hello world”串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。
引用型参数应该在能被定义为const的情况下,尽量定义为const 。