C/C++/C#面试题精选

问题(21):C#是一门托管语言,那么是不是说明只要用C#,就能保证不会出现内存泄露和其他资源泄漏?如果不是,在哪些情况下可能会出现泄漏?

答案:C#不能保证没有资源泄漏。比如如下几种情况可能会造成资源泄漏:(1) 调用Nativecode,比如用P/Invoke或者调用COM;(2) 读写文件时的,没有及时closestream, 或者ADO.NET连数据库时,没有及时关闭连接,也算资源泄漏?(3)注册事件后没有remove,导致publisher和subscriber的强依 赖,垃圾回收可能会被推迟;(4).NET还定义了一些方法直接申请非托管内存,比如Marshal.AllocHGlobal和Marshal.AllocCoTaskMem。通过这种方式得到的内存,如果没有及时释放,也会造成内存泄露。

问题(22):下面的两段C#有哪些不同?

view plain copy to clipboard print ?
  1. static void CatchException1() 
  2.     try 
  3.     { 
  4.         Function(); 
  5.     } 
  6.     catch 
  7.     { 
  8.         throw
  9.     } 
  10.  
  11. static void CatchException2() 
  12.     try 
  13.     { 
  14.         Function(); 
  15.     } 
  16.     catch (Exception e) 
  17.     { 
  18.         throw e; 
  19.     } 
static void CatchException1() { try { Function(); } catch { throw; } } static void CatchException2() { try { Function(); } catch (Exception e) { throw e; } } 答案:两个函数的catch都是重新抛出截获的exception,但抛出的exception的callstack是不一样的。对于第一种方法,exception的callstack是从最开始的抛出地点开始的。对于第二种方法,exception的callstack是从CatchException2开始的,最初抛出的地方相关的信息被隐藏了。

问题(23):运行下图中的C++代码,打印出的结果是什么?

view plain copy to clipboard print ?
  1. bool Fun1(char* str) 
  2.     printf("%s\n",str); 
  3.     return false
  4.  
  5. bool Fun2(char* str) 
  6.     printf("%s\n",str); 
  7.     return true
  8.  
  9. int _tmain(int argc, _TCHAR* argv[]) 
  10.     bool res1,res2; 
  11.     res1 = (Fun1("a")&& Fun2("b")) || (Fun1("c") || Fun2("d")); 
  12.     res2 = (Fun1("a")&& Fun2("b")) &&(Fun1("c") || Fun2("d")); 
  13.  
  14.     return res1|| res2; 
bool Fun1(char* str) { printf("%s\n",str); return false; } bool Fun2(char* str) { printf("%s\n",str); return true; } int _tmain(int argc, _TCHAR* argv[]) { bool res1,res2; res1 = (Fun1("a")&& Fun2("b")) || (Fun1("c") || Fun2("d")); res2 = (Fun1("a")&& Fun2("b")) &&(Fun1("c") || Fun2("d")); return res1|| res2; } 答案:打印出4行,分别是a、c、d、a。

在C/C++中,与、或运算是从左到右的顺序执行的。在计算rest1时,先计算Fun1(“a”)&& Func2(“b”)。首先Func1(“a”)打印出内容为a的一行。由于Fun1(“a”)返回的是false,无论Func2(“b”)的返回值是true还是false,Fun1(“a”)&& Func2(“b”)的结果都是false。由于Func2(“b”)的结果无关重要,因此Func2(“b”)会略去而不做计算。接下来计算Fun1(“c”)|| Func2(“d”),分别打印出内容c和d的两行。

                在计算rest2时,首先Func1(“a”)打印出内容为a的一行。由于Func1(“a”)返回false,和前面一样的道理,Func2(“b”)会略去不做计算。由于Fun1(“a”)&& Func2(“b”)的结果是false,不管Fun1(“c”)&& Func2(“d”)的结果是什么,整个表达式得到的结果都是false,因此Fun1(“c”) || Func2(“d”)都将被忽略。

问题(24):运行下面的C#代码,打印出来的结果是什么?

view plain copy to clipboard print ?
  1. struct Person 
  2.     public string Name; 
  3.  
  4.     public overridestring ToString() 
  5.     { 
  6.         return Name; 
  7.     } 
  8.  
  9. class Program 
  10.     static void Main(string[]args) 
  11.     { 
  12.         ArrayListarray = new ArrayList(); 
  13.         Personjim = new Person(){Name ="Jim"}; 
  14.         array.Add(jim); 
  15.  
  16.         Personfirst = (Person)array[0]; 
  17.         first.Name = "Peter"
  18.  
  19.         Console.WriteLine(array[0].ToString()); 
  20.     } 
struct Person { public string Name; public override string ToString() { return Name; } } class Program { static void Main(string[]args) { ArrayListarray = new ArrayList(); Personjim = new Person(){Name = "Jim"}; array.Add(jim); Personfirst = (Person)array[0]; first.Name = "Peter"; Console.WriteLine(array[0].ToString()); } } 答案:Person的定义是一个struct,因此是一个值类型。在运行到语句Person first =(Person)array[0]的时候,first是array[0]的一个拷贝,first和array[0]不是一个实例。因此修改first对array[0]没有影响。

问题(25):运行下面的C++代码,打印的结果是什么?

view plain copy to clipboard print ?
  1. class Base 
  2. public
  3.     voidprint() { doPrint();} 
  4.  
  5. private
  6.     virtual void doPrint() {cout <<"Base::doPrint" << endl;} 
  7. }; 
  8.  
  9. class Derived : public Base 
  10. private
  11.     virtual void doPrint() {cout <<"Derived::doPrint" << endl;} 
  12. }; 
  13.  
  14. int _tmain(int argc, _TCHAR* argv[]) 
  15.     Base b; 
  16.     b.print(); 
  17.  
  18.     Derived d; 
  19.     d.print(); 
  20.  
  21.     return 0; 
class Base { public: voidprint() { doPrint();} private: virtual void doPrint() {cout << "Base::doPrint" << endl;} }; class Derived : public Base { private: virtual void doPrint() {cout << "Derived::doPrint" << endl;} }; int _tmain(int argc, _TCHAR* argv[]) { Base b; b.print(); Derived d; d.print(); return 0; }

答案:输出两行,分别是Base::doPrint和Derived::doPrint。在print中调用doPrint时,doPrint()的写法和this->doPrint()是等价的,因此将根据实际的类型调用对应的doPrint。所以结果是分别调用的是Base::doPrint和Derived::doPrint2。如果感兴趣,可以查看一下汇编代码,就能看出来调用doPrint是从虚函数表中得到函数地址的。


博主何海涛对本博客文章享有版权。网络转载请注明出处http://blog.csdn.net/cadcisdhht。整理出版物请和作者联系。有任何建议或意见,欢迎在评论中告知,或者加我微博http://weibo.com/zhedahht与我交流。

你可能感兴趣的:(C/C++/C#面试题精选)