面试问题:
编写程序判断一个变量是不是指针?
指针的判别:
匹配顺序示例:
可以看到匹配顺序符合我们的结论。
定义一个函数模板和一个同名的变参函数,给的参数如果是指针,编译器会先匹配模板。不是指针的话只能匹配变参函数。
实验:
第41行我们看到输出了非法指令,这是为什么呢,因为变参函数是C语言的特性,41行匹配到了变参函数,而C语言中没有对象的概念,因此,我们在41行传入t对象会报非法指令的错误。
缺陷分析:
只让编译器匹配,但是不运行,以用来解决上述函数调用的问题:使用sizeof
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Test 7 { 8 public: 9 Test() 10 { 11 } 12 virtual ~Test() 13 { 14 } 15 }; 16 17 template 18 <typename T> 19 char IsPtr(T* v) // match pointer 20 { 21 return 'd'; 22 } 23 24 int IsPtr(...) // match non-pointer 25 { 26 return 0; 27 } 28 29 #define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char)) 30 31 int main(int argc, char *argv[]) 32 { 33 int i = 0; 34 int* p = &i; 35 36 cout << "p is a pointer: " << ISPTR(p) << endl; // true 37 cout << "i is a pointer: " << ISPTR(i) << endl; // false 38 39 Test t; 40 Test* pt = &t; 41 42 cout << "pt is a pointer: " << ISPTR(pt) << endl; // true 43 cout << "t is a pointer: " << ISPTR(t) << endl; // false 44 45 return 0; 46 }
运行结果如下:
面试问题:
如果构造函数中抛出异常会发生什么?
实验:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Test 7 { 8 public: 9 Test() 10 { 11 cout << "Test()" << endl; 12 13 throw 0; 14 } 15 virtual ~Test() 16 { 17 cout << "~Test()" << endl; 18 } 19 }; 20 21 22 int main(int argc, char *argv[]) 23 { 24 Test* p = reinterpret_cast<Test*>(1); 25 26 try 27 { 28 p = new Test(); 29 } 30 catch(...) 31 { 32 cout << "Exception..." << endl; 33 } 34 35 cout << "p = " << p << endl; 36 37 return 0; 38 }
结果如下:
可以看到28行p指针的值没有被赋值,在35行依旧打印出了1。
在构造函数中抛出异常,new关键字是不会返回一个值的,也不会返回空指针。在这种情况下不会发生内存泄漏,Test对象的内存会被回收。
使用内存检测工具进行检测:
可以看到0 byte in 0 blocks,说明在程序结束时是没有内存泄漏的。
我们将13行的throw注释掉,再次使用内存检测工具检测,结果如下:
析构函数中的抛出异常:
小结: