【C++】 67_经典问题分析 五
生活随笔
收集整理的這篇文章主要介紹了
【C++】 67_经典问题分析 五
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
面試問(wèn)題 一
編寫(xiě)程序判斷一個(gè)變量是不是指針
指針的判別
-
拾遺
- C++ 中仍然支持 C 語(yǔ)言中的可變函數(shù)參數(shù)
-
C++ 編譯器的匹配調(diào)用優(yōu)先級(jí)
- 重載函數(shù)
- 函數(shù)模板
- 變參函數(shù)
-
思路
- 將變量分為兩類: 指針 VS 非指針
-
編寫(xiě)函數(shù):
- 指針變量調(diào)用時(shí)返回 true
- 非指針變量調(diào)用時(shí)返回 false
- 函數(shù)模板與變參函數(shù)的化學(xué)反應(yīng)
編程實(shí)驗(yàn): 指針判斷
#include <iostream>using namespace std;class Test { public:Test(){};virtual ~Test(){}; };template < typename T > bool IsPtr(T* v) // match pointer {return true; }bool IsPtr(...) // match non-pointer {return false; }int main() {int i = 0;int* p = &i;cout << "p is a pointer: " << IsPtr(p) << endl;cout << "i is a pointer: " << IsPtr(i) << endl;Test t;Test* pt = &t;cout << "pt is a pointer: " << IsPtr(pt) << endl;cout << "t is a pointer: " << IsPtr(t) << endl; // 注意這里!對(duì)象傳入變參函數(shù)return 0; } 編譯輸出: test.cpp: In function ‘int main()’: test.cpp:40: warning: cannot pass objects of non-POD type ‘class Test’ through ‘...’; call will abort at runtime運(yùn)行輸出: p is a pointer: 1 i is a pointer: 0 pt is a pointer: 1 非法指令-
存在的缺陷:
- 變參函數(shù)無(wú)法解析對(duì)象參數(shù),可能造成程序崩潰!!
-
進(jìn)一步的挑戰(zhàn):
- 如何讓編譯器精準(zhǔn)匹配函數(shù),但不進(jìn)行實(shí)際的調(diào)用?
編程實(shí)驗(yàn): 指針判斷改進(jìn)
#include <iostream>using namespace std;class Test { public:Test(){};virtual ~Test(){}; };template < typename T > char IsPtr(T* v) // match pointer {return 'd'; }int IsPtr(...) // match non-pointer {return 0; }#define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char)) // 注意這里!int main() {int i = 0;int* p = &i;cout << "p is a pointer: " << ISPTR(p) << endl;cout << "i is a pointer: " << ISPTR(i) << endl;Test t;Test* pt = &t;cout << "pt is a pointer: " << ISPTR(pt) << endl;cout << "t is a pointer: " << ISPTR(t) << endl;return 0; } 輸出:【無(wú)警告,無(wú)錯(cuò)誤】 p is a pointer: 1 i is a pointer: 0 pt is a pointer: 1 t is a pointer: 0分析: sizeof(IsPtr(t)) 發(fā)生了什么?
- sizeof 是編譯器的內(nèi)置指示符;
- 在編譯過(guò)程中所有的 sizeof 將被具體的數(shù)值所替換;
- 程序的執(zhí)行過(guò)程與 sizeof 沒(méi)有任何關(guān)系;
編譯器根據(jù)匹配規(guī)則匹配到具體的函數(shù) int IsPtr(...);
sizeof(IsPtr(t)); 編譯器將計(jì)算函數(shù)返回值類型所占用的大小;
使用計(jì)算出的數(shù)值整體替換 sizeof(IsPtr(t)),因此不會(huì)發(fā)生實(shí)際的運(yùn)行調(diào)用。
不會(huì)出現(xiàn)變參函數(shù)解析對(duì)象參數(shù)而出現(xiàn)的程序運(yùn)行時(shí)錯(cuò)誤。
面試問(wèn)題 二
如果構(gòu)造函數(shù)中拋出異常會(huì)發(fā)生什么情況呢?
構(gòu)造中的異常
-
構(gòu)造函數(shù)中拋出異常
- 構(gòu)造過(guò)程立即停止
- 當(dāng)前對(duì)象無(wú)法生成
- 析構(gòu)函數(shù)不會(huì)被調(diào)用
- 對(duì)象所占用的空間立即收回
-
工程中的建議
- 不要在構(gòu)造函數(shù)中拋出異常
- 當(dāng)構(gòu)造函數(shù)可能產(chǎn)生異常時(shí),使用二階構(gòu)造模式
編程實(shí)驗(yàn): 構(gòu)造中的異常
#include <iostream>using namespace std;class Test { public:Test(){cout << "Test() begin ..." << endl;throw 0;cout << "Test() end ..." << endl;}virtual ~Test(){cout << "~Test()" << endl;} };int main() {Test* p = reinterpret_cast<Test*>(1);cout << "p = " << p << endl;try{p = new Test();}catch(...){cout << "Exception..." << endl;}cout << "p = " << p << endl;return 0; } 輸出: p = 0x1 Test() begin ... Exception... p = 0x1注意: "Test() end ..." 沒(méi)有打印 ==> 證明構(gòu)造過(guò)程停止; "~Test()" 沒(méi)有打印 ==> 證明析構(gòu)函數(shù)不會(huì)被調(diào)用; p 的值沒(méi)有發(fā)生改變 ==> 證明對(duì)象沒(méi)有生成;內(nèi)存分析:
g++ -g test.cpp valgrind --tool=memcheck --leak-check=full ./a.out輸出:對(duì)象所占用的內(nèi)存空間被收回
==28776== HEAP SUMMARY: ==28776== in use at exit: 0 bytes in 0 blocks ==28776== total heap usage: 2 allocs, 2 frees, 104 bytes allocated ==28776== ==28776== All heap blocks were freed -- no leaks are possible析構(gòu)中的異常
- 避免在析構(gòu)函數(shù)中拋出異常!!
- 析構(gòu)函數(shù)的異常將導(dǎo)致: 對(duì)象所使用的資源可能無(wú)法完全釋放
編程實(shí)驗(yàn): 析構(gòu)中的異常
#include <iostream>using namespace std;class Test { private:int* m_pointer; public:Test(){cout << "Test()" << endl;m_pointer = new int(0);}virtual ~Test(){cout << "~Test() begin ..." << endl;throw 0;delete m_pointer;cout << "~Test() end ..." << endl;} };int main() {try{Test();}catch(...){cout << "Exception..." << endl;}return 0; } 輸出: Test() ~Test() begin ... Exception...小結(jié)
- C++ 中依然支持變參函數(shù)
- 變參函數(shù)無(wú)法很好的處理對(duì)象參數(shù)
- 利用函數(shù)模板和變參函數(shù)能夠判斷指針變量
- 構(gòu)造函數(shù)和析構(gòu)函數(shù)中不要拋出異常
以上內(nèi)容參考狄泰軟件學(xué)院系列課程,請(qǐng)大家保護(hù)原創(chuàng)!
總結(jié)
以上是生活随笔為你收集整理的【C++】 67_经典问题分析 五的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2018年第41周-sparkSql搭建
- 下一篇: 学习笔记——基本光照模型简单实现