C++基礎知識面試必備、複習細節 (8)(tuple、隨機數、異常處理、多繼承)
tuple類型
-
tuple是一個類似於pair的模板,pair類型是每個成員變量各自可以是任意類型,但是隻能有兩個成員,而tuple與pair不同的是它可以有任意數量的成員
-
個人常把tuple當作一個結構體使用,如果只是一次使用的話就避免了結構體繁瑣的創建
-
tuple的基本操作:
tuple<int,string,int> t{1,"James",1000}; //可以用來存一個序號,名字,工資這樣的信息 auto t=make_tuple("1","James","12345678911"); //存序號,名字,電話 用auto可以自動判斷 auto name=get<1>(t); //返回名字 通過get<i>(tuple)返回第i-1個成員對象 get<2>(t)="98765432111"; //get<>()返回的是引用,因此可以修改
-
兩個tuple相等當且僅當元素數量相同且每個元素相等,< 也是同理
-
通過使用tuple可以令一個函數中返回多個值, 有時候可以令程序更簡潔方便
隨機數
-
頭文件: random
-
c++的隨機數通過兩部分解決隨機數問題:隨機數引擎類和隨機數分佈類
隨機數引擎類生成隨機的unsigned整數序列,隨機數分佈類使用引擎返回特定概率分佈的隨機數
-
常用的默認隨機數引擎生成隨機數:
default_random_engine e; for (int i = 0; i < 10;i++) cout << e() << ' '; /* 16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709 */
-
使用分佈類型的對象得到指定範圍的隨機數
uniform_int_distribution<unsigned> u(0, 9); //生成0-9的隨機數 default_random_engine e; for (int i = 0; i < 10; i++) cout << u(e) << ' '; //0 1 7 4 5 2 0 6 6 9
-
一個給定的隨機數發生器一直會生成相同的隨機數序列。一個函數如果定義了局部的隨機數發生器,應該將其(包括引擎和分佈對象)定義爲static的,否則每次調用生成相同的序列。
-
生成正態分佈序列
default_random_engine e; normal_distribution<> n(4, 1.5); //均值爲4,標準差爲1.5的正態分佈 for (int i = 0; i < 10; i++) cout << n(e) << ' '; //3.81705 2.36977 5.02643 2.38722 4.0499 5.11725 4.05041 3.21004 4.6938 4.30105
-
生成伯努利分佈序列(true or false 可以制定概率)
default_random_engine e; bernoulli_distribution n(0.9); //伯努利實驗的p=0.9 for (int i = 0; i < 10; i++) cout << n(e) << ' '; //1 1 1 1 0 1 1 1 1 1
IO庫
-
八進制十六進制十進制
cout<<hex<<20<<endl; //14 將cout輸出的整數轉換爲16進制 cout<<oct<<10<<endl; //12 將cout輸出的整數轉換爲8進制 cout << dec << 10<<endl;//10 將cout輸出的整數轉換爲10進制 cout<<0x20<<endl; //0x開頭表示十六進制 32 cout << 010 << endl; //0開頭表示八進制 8
-
浮點數輸出格式
//制定打印精度 double t = 3.1415926; cout.precision(3); //浮點數精度爲3 cout << t << endl; //3.14 cout.precision(5); cout <<t << endl; //3.1416
異常處理
-
執行throw時,跟在throw後面的語句將不再執行,程序的控制權從throw轉移到catch塊。因此,儘量不要在析構函數中寫異常處理,避免內存泄漏。
-
棧展開:對於拋出異常的函數的調用語句位於一個try語句塊內,則檢查與該try塊關聯的catch語句。如果找到了匹配的catch,則用該catch處理異常,否則如果該try語句嵌套在其他try塊中,則繼續檢查與外層try匹配的catch語句,如果還沒找到則退出當前的主調函數,繼續在調用了這個函數的其他函數中尋找。
棧展開過程也就是沿着嵌套函數的調用鏈不斷查找,直到找到了與異常匹配的catch子句爲止,或者一直沒找到,退出主函數後終止查找過程。
-
一個異常沒被捕獲,則將終止程序
-
構造函數中拋出異常,會導致析構函數不能被調用,但對象本身已申請到的內存資源會被系統釋放
因爲析構函數不能被調用,所以可能會造成內存泄露或系統資源未被釋放
構造函數中可以拋出異常,但必須保證在構造函數拋出異常之前,把系統資源釋放掉,防止內存泄露
-
不要在析構函數中拋出異常
如果某個操作可能會拋出異常,class應提供一個普通函數(而非析構函數),來執行該操作
如果析構函數中異常非拋不可,那就用try catch來將異常吞下,不要讓異常逃離析構函數
-
try { //something } catch (exception &e) { cout << "Standard exception: " << e.what() << endl; }
多繼承
- 如果從多個基類中繼承了相同的構造函數,則該類必須定義自己的構造函數
- 當一個類擁有多個基類時,可能出現派生類從兩個或多個基類中繼承了同名成員的情況,則需要用前綴限定符訪問該函數,否則會有二義性
- 虛繼承:令某個類做出聲明,使其共享基類。在這樣的情況下,虛基類被多次繼承,也只有一個共享的基類 virtual public A
- 虛派生隻影響從指定了虛基類的派生類中進一步派生出的類,它不會影響派生類本身
- 虛基類總是先於非虛基類構造,與它們在繼承體系中的次序和爲止無關
- 多繼承的父類的構造順序,只與繼承的順序有關,與成員初始化列表順序無關
- 多繼承的構造函數的順序:
- 虛基類的構造函數按照它們被繼承的順序構造
- 非虛基類的構造函數按照它們被繼承的順序構造;
- 成員對象的構造函數按照它們聲明的順序調用
- 類自己的構造函數
- 析構函數調用順序與構造函數相反