日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++】 67_经典问题分析 五

發布時間:2025/3/17 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++】 67_经典问题分析 五 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

面試問題 一

編寫程序判斷一個變量是不是指針

指針的判別

  • 拾遺

    • C++ 中仍然支持 C 語言中的可變函數參數
    • C++ 編譯器的匹配調用優先級

    • 重載函數
    • 函數模板
    • 變參函數

  • 思路

    • 將變量分為兩類: 指針 VS 非指針
    • 編寫函數:

      • 指針變量調用時返回 true
      • 非指針變量調用時返回 false

  • 函數模板與變參函數的化學反應
template < typename T > bool IsPtr(T* v) // match pointer {return true; }bool IsPtr(...) // match non-pointer {return false; }

編程實驗: 指針判斷

#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; // 注意這里!對象傳入變參函數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運行輸出: p is a pointer: 1 i is a pointer: 0 pt is a pointer: 1 非法指令
  • 存在的缺陷:

    • 變參函數無法解析對象參數,可能造成程序崩潰!!

  • 進一步的挑戰:

    • 如何讓編譯器精準匹配函數,但不進行實際的調用?

編程實驗: 指針判斷改進

#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; } 輸出:【無警告,無錯誤】 p is a pointer: 1 i is a pointer: 0 pt is a pointer: 1 t is a pointer: 0

分析: sizeof(IsPtr(t)) 發生了什么?

  • sizeof 是編譯器的內置指示符;
  • 在編譯過程中所有的 sizeof 將被具體的數值所替換;
  • 程序的執行過程與 sizeof 沒有任何關系;

編譯器根據匹配規則匹配到具體的函數 int IsPtr(...);
sizeof(IsPtr(t)); 編譯器將計算函數返回值類型所占用的大小;
使用計算出的數值整體替換 sizeof(IsPtr(t)),因此不會發生實際的運行調用。
不會出現變參函數解析對象參數而出現的程序運行時錯誤。

面試問題 二

如果構造函數中拋出異常會發生什么情況呢?

構造中的異常

  • 構造函數中拋出異常

    • 構造過程立即停止
    • 當前對象無法生成
    • 析構函數不會被調用
    • 對象所占用的空間立即收回

  • 工程中的建議

    • 不要在構造函數中拋出異常
    • 當構造函數可能產生異常時,使用二階構造模式

編程實驗: 構造中的異常

#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 ..." 沒有打印 ==> 證明構造過程停止; "~Test()" 沒有打印 ==> 證明析構函數不會被調用; p 的值沒有發生改變 ==> 證明對象沒有生成;

內存分析:

g++ -g test.cpp valgrind --tool=memcheck --leak-check=full ./a.out

輸出:對象所占用的內存空間被收回

==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

析構中的異常

  • 避免在析構函數中拋出異常!!
  • 析構函數的異常將導致: 對象所使用的資源可能無法完全釋放

編程實驗: 析構中的異常

#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...

小結

  • C++ 中依然支持變參函數
  • 變參函數無法很好的處理對象參數
  • 利用函數模板和變參函數能夠判斷指針變量
  • 構造函數和析構函數中不要拋出異常

以上內容參考狄泰軟件學院系列課程,請大家保護原創!

總結

以上是生活随笔為你收集整理的【C++】 67_经典问题分析 五的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。