【备战2014笔面试】C++经典笔试30题(21-30)

1.       为什么Delete会出错?

  1. <span style="font-size:14px;">class CBase  
  2. {  
  3. public:  
  4.          CBase() { cout <<"CBase" << endl; }  
  5.          virtual ~CBase() { cout <<"~CBase" << endl;}  
  6. };  
  7.    
  8. classCDerived : public CBase  
  9. {  
  10. public:  
  11.          CDerived() { cout <<"CDerived" << endl; }  
  12.          ~CDerived() { cout <<"~CDerived" << endl; }  
  13. };  
  14.    
  15. int main()  
  16. {  
  17.          CBase base;  
  18.          CBase* pBase = new CBase;  
  19.          pBase = &base;  
  20.          delete pBase; //运行时报错!  
  21. }</span>  


【分析如下】:

1.pBase指向了栈区内存,那是系统管理的空间,不能用delete释放的。

2.程序在堆区new的空间最后没有被释放,造成了内存泄露。

3.最好不要随便把申请到堆区空间的指针指向别处,至少也要有一个指针指向申请的空间。以便最后释放的是自己申请的那块内存。

【修正后做法】:

  1. <span style="font-size:14px;">int main()  
  2. {  
  3.     CBase base;  
  4.     CBase* pBase = new CBase;  
  5.     CBase* pBase2 = pBase;   //至少也要有一个指针指向申请的空间  
  6.     pBase = &base;  
  7.     delete pBase2;  //以便最后释放的是自己申请的那块内存。  
  8. //运行时不再报错!</span>  

【再深入点】:程序有两个问题:

1.内存泄露,new出来的没delete;

2.两次析构;base不是new出来,在生命周期结束(也就是你函数结束的时候)会自动释放,你主动调用delete将其析构,系统在函数结束时又会对其析构,所以才会报错。而且报错的地方应该是程序退出时

 

2.       类中静态常成员变量的定义?

  1. <span style="font-size:14px;">#include<iostream>  
  2. usingnamespace std;  
  3. //可以在类的声明中对常量的类变量进行赋值  
  4. //VS2008可以,vc6.0不可以。和编译器有关。  
  5. class myclass  
  6. {  
  7. public:  
  8.          static const int i=20; //只有类的静态常量数据成员才可以在类中初始化。  
  9. };  
  10. const int myclass::i = 10;  
  11. int main()  
  12. {  
  13.          cout<<myclass::i<<endl;  
  14.          return 0;  
  15. }</span>  

3.      重载和多态的关系?

不同点

重载overload

覆盖override

1.是否支持多态?

不支持

支持

2.存在形式?

可以在类中或在C++语言中都可以体现

存在于类中父类、子类之间。

3.参数列表、返回值

参数列表或返回值不同,或二者都不同。

参数列表、返回指标必须相同。

 

 

4.      输出格式:printf用!

%a(%A)    

浮点数、十六进制数字和p-(P-)记数法(C99)

%c           

字符

%d            

有符号十进制整数

%f             

浮点数(包括floatdoulbe)

%e(%E)    

浮点数指数输出[e-(E-)记数法]

%g(%G)    

浮点数不显无意义的零"0"

%i             

有符号十进制整数(%d相同)

%u            

无符号十进制整数

%o            

八进制整数    e.g.     0123

%x(%X)     

十六进制整数0f(0F)   e.g.   0x1234

%p            

指针

%s            

字符串

     

5.      一个参数或指针可以既是const又是volatile)解读?

Volatile 以防止编译器将其优化成从寄存器中读取。一个定义为volatile的变量时说这个变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

一个参数可以既是const又是volatile,const是不让程序修改,volatile是意想不到的改变,不是程序修改。一个指针也可以是volatile,中断服务子程序修改一个指向buffer的指针。

6.      Little Endian低字节序(由低字节—>高字节存储);计算机默认的为低字节序。

High Endian高字节序(由高字节—>低字节存储);

  1. <span style="font-size:14px;">typedef struct bitstruct  
  2. {  
  3.          int b1:5;  
  4.          int b2:2;  
  5.          int b3:2;  
  6. }bitstruct;  
  7.    
  8. int main()  
  9. {  
  10.          bitstruct b;  
  11.          memcpy(&b,"EMCEXAMINATION",sizeof(b));  
  12.    
  13.          cout << sizeof(b) << endl;  
  14.    
  15.          printf("%d,%d\n",b.b1,b.b2);//5,-2  
  16.          return 0;  
  17. }</span>  

[解读]:1.sizeof(b)=4;即4个字节的大小。

2.memcpy将”EMC …”存入b中。

3.实质b中只有5+2+2,9位。即对应字符也只有”EM”.E的ASCII码为0X45,M的ASCII码为0X4D。

满足高字节—>低字节存储0X4D0X45,对应二进制位:01001101 0100 0101

4.对应的b1,满足(低字节存放于低位)取得后低地址的5位0 0101,首位为0代表正数,大小为5。

对应的b2,取10,首位为1代表负数,取补码后得到b2=-2。

27.输出结果?

  1. <span style="font-size:14px;">int main()  
  2. {  
  3.          int a[5][2] = {0,1,2,3,4,5,6,7,8,9};  
  4.           
  5.          int *p = a[0];  
  6.          int (*p2)[2] = &a[1];  
  7.          ++p;  
  8.          ++p2;  
  9.           
  10.          printf("%d\n",*p); //1 p 是整型指针,初始指向元素0,加1指向1  
  11.          printf("%d\n",**p2); //4 p2是含2个元素的数组指针,初始指向元素2,该指针加1是向后移动2个数据,所以指向4  
  12.          printf("%d \n",p2[1][2]); //如何解读? 见下解读。   
  13.          return 0;  
  14. }</span>  

 

0

1

0

0 (p)

1(++p后)

1

2  (P2指向)

3

2

4 (++p2后)

5

3

6  (p2+1后)

7

4

8  (p2[1][2])

9

 

解读:p2是一个指针(指向数组的指针),是一个指向包含两个元素数组的指针变量。和普通的指针不同的地方时它指向的长度为2。(*p2)[2]和a是等价的。

对于p2[1][2],此时p2指向4,前一个下标1就是p2指针再加1指向6,后一个下标加2移动2个元素,指向了8。


28.拷贝构造输出结果?

  1. <span style="font-size:14px;">class A  
  2. {  
  3.     static int objectCount;  
  4. public:  
  5.     A()  
  6.     {  
  7.         objectCount++;  
  8.         cout << "A():" <<objectCount << endl;  
  9.     }  
  10.      
  11.     A(const A& r)  
  12.     {  
  13.         objectCount++;  
  14.         cout << "A(const A&r):" << objectCount << endl;  
  15.     }  
  16.           
  17.     ~A()  
  18.     {  
  19.         objectCount--;  
  20.         cout << "~A():"<< objectCount << endl;  
  21.     }  
  22. };  
  23.    
  24. intA::objectCount = 0;  
  25.    
  26. A f(A x)          
  27. {  
  28.     cout << endl <<  "Begin: f(A x)" << endl;  
  29.     return x;   //【临时对象】调用默认拷贝构造函数A(const A& r):3  
  30. }                //~A():2  
  31.    
  32. int main()  
  33. {  
  34.     A h;        //A():1  
  35.     A h2 = f(h); //调用默认拷贝构造函数A(constA& r):2  
  36.     cout << endl <<"End(main): f(A x)" << endl << endl;  
  37.           
  38.     return 0;     
  39. }               //~A():1  析构h2     
  40. //~A():0  构函h</span>  

29.四类强制类型转换

类型

示意

举例

static_cast

1.类型转换,编译器隐式执行的任何类型都可由static_cast显示完成;2.使用类型信息执行转换,在转换执行必要的检测(越界检测、类型检查),操作相对安全;

int—>double

int ival;

double result = static_cast<double> ival

const_cast

转换掉对象的const属性

下举例

dynamic_cast

运行时类型检查,用于继承体制下的由上到下的转换downcast。

下举例

reinterpret_cast

1.仅仅重新编译了给定对象的比特模型,而没有进行二进制转换;2.为操作数提供低层次的重新解释。

下举例

举例:

  1. <span style="font-size:14px;">//const_cast 实例.  
  2. class B  
  3. {  
  4. public:  
  5.          int m_num;  
  6. };  
  7.    
  8. int main()  
  9. {  
  10.          B b0;  
  11.          b0.m_num = 100;  
  12.          const B b1 = b0;  
  13.          cout << b0.m_num<< " " << b1.m_num << endl;  
  14. // 以下修改const对象的值是错误的。  
  15. //       b1.m_num = 355;  
  16. //       cout << b1.m_num <<endl;  // error C2166: l-value specifiesconst object  
  17.    
  18. //以下使用const_cast是正解.  
  19.          const_cast<B&>(b1).m_num =355;  
  20.          cout<< b1.m_num << endl;  
  21.          return 0;  
  22. }  
  23.    
  24. //reinterpret_cast实例  
  25. int main()  
  26. {  
  27.          int n = 9;  
  28.          double dval =reinterpret_cast<double& >(n);  
  29.          double dval_new =static_cast<double>(n); //成功.  
  30.          //[仅仅复制了n的比特位到d,没有进行必要的分析]  
  31.          cout << dval << endl;//2.64214e-308  
  32.          cout << dval_new << endl;//9  
  33.          return 0;  
  34. }  
  35. //dynamic_cast实例  
  36. class B  
  37. {  
  38. public:  
  39.          B() { cout << "B()"<< endl; }  
  40.          ~B() { cout << "~B()"<< endl; }  
  41. };  
  42. class C :public B  
  43. {  
  44. public:  
  45.          C() { cout << "C()"<< endl; }  
  46.          ~C() { cout << "~C()"<< endl; }  
  47. };  
  48. class D :public C  
  49. {  
  50. public:  
  51.          D(){ cout << "D()"<< endl; }  
  52.          ~D(){ cout << "~D()"<< endl; }  
  53. };  
  54.    
  55. void f(D* pd)  
  56. {  
  57.          C* pc =dynamic_cast<C*>(pd);   // ok: C isa direct base class  
  58.          // pc points to C subobject of pd  
  59.    
  60.          B* pb =dynamic_cast<B*>(pd);   // ok: B isan indirect base class  
  61.          // pb points to B subobject of pd      
  62. }  
  63.    
  64. int main()  
  65. {  
  66.          D objd;  
  67.          f(&objd);  
  68.          return 0;  
  69. }</span>  

30. 持续更新中......

30. 如何在C/C++中显示当前程序所在的文件名及行号。

——这个当时没答上来,见过没记住。今天查了下MSDN如下:

__FILE__, //用于显示文件名的宏 %s, 格式如【F:\NeuSoftDemo\NeuSoftDemo.cpp】;__LINE__, //用于显示行号的宏 %d,格式如【12】;

扩展》》__DATE__, //用于显示当前日期,格式如【Sep 18 2012】 %s; __TIME__, //用于显示当前时间,格式如【09:45:01】 %s;

__TIMESTAMP__,//用于显示当前日期和时间,格式如【Tue Sep 18 09:48:07 2012】 %s。

31. 程序纠错题:

  1. int main(int argc,char* argv[])
  2. {
  3. char str[5][] = {"First","Second","Thrid","Four","Five"};
  4. char* p[] = {str[4],str[3],str[2],str[1],str[0]};

  5. for(int i = 0; i < 5; i++)
  6. {
  7. printf("%c\n",*(p+i));
  8. }

  9. return 0;
  10. }
  1. int main(int argc, char* argv[])  
  2. {  
  3.     char str[5][] = {"First","Second","Thrid","Four","Five"};  
  4.     char* p[] = {str[4],str[3],str[2],str[1],str[0]};  
  5.       
  6.     for(int i = 0; i < 5; i++)  
  7.     {  
  8.         printf("%c\n",*(p+i));  
  9.     }  
  10.   
  11.     return 0;  
  12. }  
个人感觉如下:

错误1: char str[5][] 定义出错,需要指定第一维的个数,改为char str[][5]吗?但后面的字符串如"Second"6个字符,还有'\0'。改为:char* str[5]比较稳妥;

错误2: printf("%c\n",*(p+i)); 显然*(p+i) 等价于p[i]存储的是字符串,所以%c应该改为%s。(%c打印的是单个字符,%s打印的是字符串)。

修正后如下:

[cpp] 
  1. int main(int argc,char* argv[])
  2. {
  3. char *str[5] = {"First","Second","Thrid","Four","Five"};
  4. char* p[] = {str[4],str[3],str[2],str[1],str[0]};

  5. for(int i = 0; i < 5; i++)
  6. {
  7. printf("%s\n",*(p+i));
  8. }

  9. return 0;
  10. }

33. 递归与非递归实现二分查找。

//非递归实现-

void binarySearchUncycle(int nArr[],int nSize,int nSearchVal)
{
    int nLow = 0;
    int nHigh = nSize-1;
    int nMid = 0;
    bool bFound = false;
    while(nLow <= nHigh)
    {
        nMid = (nLow + nHigh)/2;
        cout << "nMid =" << nMid << endl;
        if(nArr[nMid] == nSearchVal)
        {
            bFound = true;
            break;
        }
        else if(nArr[nMid] > nSearchVal)
        {
            nHigh = nMid-1;
        }
        else
        {
            nLow = nMid+1;
        }
    }//end while
    if(bFound)
    {
        cout << "The Elem " << nSearchVal << " is Exist in the array!" << endl;
    }
    else
    {
        cout << "The Elem " << nSearchVal << " is Not Exist in the array!" << endl;
    }
}

递归实现

void binarySearchUncycle(int nArr[],int nSize,int nSearchVal)
{
	int nLow = 0;
	int nHigh = nSize-1;
	int nMid = 0;
	bool bFound = false;


	while(nLow <= nHigh)
	{
		nMid = (nLow + nHigh)/2;
		cout << "nMid =" << nMid << endl;
		if(nArr[nMid] == nSearchVal)
		{
			bFound = true;
			break;
		}
		else if(nArr[nMid] > nSearchVal)
		{
			nHigh = nMid-1;
		}
		else
		{
			nLow = nMid+1;
		}
	}//end while


	if(bFound)
	{
		cout << "The Elem " << nSearchVal << " is Exist in the array!" << endl;
	}
	else
	{
		cout << "The Elem " << nSearchVal << " is Not Exist in the array!" << endl;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值