2019秋招結束,C++後臺方向知識點總結
阿新 • • 發佈:2019-01-13
作者:東北第一菜雞
連結:https://www.nowcoder.com/discuss/118716
來源:牛客網
漫漫秋招路,在今天結束了。最後拿到了百度,intel,360,oppo,vipkid,獵豹移動,秒針系統,農行總行的offer,華為還在錄用排序,期間因為時間問題放棄了一些筆試和麵試。從牛客網學到了很多,自己總結了一些知識點(C++後臺方向),分享給大家!
- C和C++語言基礎
- C++相對於C語言的優點
- 面向物件,把資料和***作繫結在一起,函式呼叫的時候看起來比較清晰
- 運算子過載
- 記憶體管理相比C好一些,比如可以用std:string
- 庫相比C多一些(比如stl)
- 可以寫工具類在多個專案中使用(比如計算程式執行時間的類,比如讀寫某個位置的檔案)
- 面向物件的三大特徵
- 封裝
- 多型
- 靜態多型
- 編譯期間就可以確定呼叫那個函式,比如函式過載
- 動態多型
- 在執行時確定呼叫那個函式,比如虛擬函式
- 靜態多型
- 繼承
- extern關鍵字作用
- extern可以置於變數或者函式前,以標示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數和函式時在其他模組中尋找其定義
- extern C 表示按C語言的規則編譯
- static關鍵字作用
- https://blog.csdn.net/explore_world/article/details/56024558
- static修飾區域性變數
- 靜態區域性變數儲存在靜態區
- 生存期為整個程式生命週期,但是其作用域仍與自動變數相同,只能在定義該變數的函式內使用該變數。退出該函式後,儘管該變數還繼續存在,但不能使用它。
- 靜態區域性變數若在宣告時未賦以初值,則系統自動賦予0值。而對自動變數不賦初值,則其值是不定的。
- static修飾全域性變數
- 非靜態全域性變數的作用域是整個源程式,也即在各個原始檔中都是有效的。
- 而靜態全域性變數則只在定義該變數的原始檔內有效,在同一源程式的其它原始檔中不能使用它
- static 函式
- static的含義是指對函式的作用域僅侷限於本檔案
- 使用靜態函式的好處是:不同的人編寫不同的函式時,不用擔心自己定義的函式,是否會與其它檔案中的函式同名,因為同名也沒有關係
- 函式中使用static修飾變數
- 變數儲存在全域性區,函式退出時變數仍然存在,但是在函式外不能訪問。
- 類中的static關鍵字
- static 資料成員
- 靜態資料成員
- 無論這個類的物件被定義了多少個,靜態資料成員在程式中也只有一份拷貝,由該型別的所有物件共享訪問
- 在沒有產生類的例項時,我們就可以***作它
- 靜態資料成員儲存在全域性資料區
- 靜態資料成員定義時才分配空間,不能在類宣告中定義(在全域性區定義)
- 同全域性變數相比,使用靜態資料成員有兩個優勢
- 靜態資料成員沒有進入程式的全域性名字空間,因此不存在與程式中其它全域性名字衝突的可能性
- 可以實現資訊隱藏。靜態資料成員可以是private成員,而全域性變數不能
- static 成員函式
- 靜態成員函式
- 無法訪問屬於類物件的非靜態資料成員和非靜態成員函式
- static 資料成員
- const的作用
- https://www.cnblogs.com/JiFfeiYu/p/6697195.html
- const修飾變數
- 變數的值不能改變
- const修飾指標
- 如果const位於*的左側,則const就是用來修飾指標所指向的變數,即指標指向為常量
- 如果const位於*的右側,const就是修飾指標本身,即指標本身是常量
- 函式中使用const
- const修飾函式引數
- 表示引數不可變
- 若引數為引用,可以增加效率
- const引用傳遞和函式按值傳遞的效果是一樣的,但按值傳遞會先建立一個類物件的副本, 然後傳遞過去,而它直接傳遞地址,所以這種傳遞比按值傳遞更有效
- 若引數為引用,可以增加效率
- 表示引數不可變
- const 修飾函式返回值
- 含義和const修飾變數和指標的含義相同
- const修飾函式引數
- 類中使用const
- const修飾成員變數
- 表示成員變數不能被修改,同時只能在初始化列表中賦值
- const修飾成員函式
- 該函式不能改變物件的成員變數
- 不能呼叫非const成員函式,因為任何非const成員函式會有修改成員變數的企圖
- const的成員函式才能被一個const類物件呼叫
- const關鍵字不能與static關鍵字同時使用,因為static關鍵字修飾靜態成員函式,靜態成員函式不含有this指標,即不能例項化,const成員函式必須具體到某一例項。
- const修飾類物件
- 物件的任何成員都不能被修改
- 只能呼叫const成員函式
- const修飾成員變數
- volatile
- 訪問暫存器要比訪問記憶體要塊,因此CPU會優先訪問該資料在暫存器中的儲存結果,但是記憶體中的資料可能已經發生了改變,而暫存器中還保留著原來的結果。為了避免這種情況的發生將該變數宣告為volatile,告訴CPU每次都從記憶體去讀取資料。
- 防止編譯器對變數的優化
- 一個引數可以即是const又是volatile的嗎?
- 可以
- new與malloc區別
- new分配記憶體按照資料型別進行分配,malloc分配記憶體按照大小分配
- new不僅分配一段記憶體,而且會呼叫建構函式,但是malloc則不會。
- new的實現原理?
- 先通過malloc申請記憶體空間,然後再呼叫建構函式
- new的實現原理?
- new返回的是指定物件的指標,而malloc返回的是void*,因此malloc的返回值一般都需要進行型別轉化;
- new是一個***作符可以過載,malloc是一個庫函式;
- new分配的記憶體要用delete銷燬,malloc要用free來銷燬;delete銷燬的時候會呼叫物件的解構函式,而free則不會;
- malloc分配的記憶體不夠的時候,可以用realloc擴容。new沒用這樣***作;
- realloc擴容的原理
- 如果當前連續記憶體塊足夠擴容的話就直接擴容,如果當前記憶體塊不夠長就再找一個足夠長的地方,分配一塊新的記憶體,將原來的內容複製過來,將原來的記憶體空間釋放。
- realloc擴容的原理
- new如果分配失敗了會丟擲bad_malloc的異常,而malloc失敗了會返回NULL。
- new和new[]的區別,new[]一次分配所有記憶體,多次呼叫建構函式,分別搭配使用delete和delete[],同理,delete[]多次呼叫解構函式,銷燬陣列中的每個物件。
- 隱藏
- 隱藏指的是子類隱藏了父類的函式
- 如果是虛擬函式則叫覆蓋
- C++多型性與虛擬函式表
- https://blog.csdn.net/haoel/article/details/1948051/
- 一個基類指標指向派生類物件,在呼叫物件虛擬函式時,就會去查詢該物件的虛擬函式表,虛擬函式表的地址存放在每個物件的頭部位置,在虛擬函式表中找到對應的虛擬函式指標,然後進行呼叫
- 沒有虛擬函式的類裡面不會有虛擬函式表,對於有虛擬函式表的類,一個類對應一個虛擬函式表,這個類的所有物件共用這個虛擬函式表,虛擬函式表的地址儲存在每個物件的頭部位置
- 派生類的虛擬函式表從基類繼承過來,如果覆蓋了其中的某個虛擬函式,則虛擬函式表裡面該函式對應的指標被替換
- 虛擬函式不能是靜態成員函式??,其訪問許可權可以是protected或public
- 虛擬函式的作用
- 實現多型
- 動態繫結是如何實現
- 純虛擬函式
- https://blog.csdn.net/guoyong10721073/article/details/52414029
- 定義的例子:virtual int fun()=0;
- 在基類中抽象出一個方法,且該基類只做能被繼承,而不能被例項化
- 這個方法必須在派生類中被實現
- 友元函式
- https://blog.csdn.net/qq_26337701/article/details/53996104
- 類中通過使用關鍵字friend 來修飾友元函式,但該函式並不是類的成員函式,其宣告可以放在類的私有部分,也可放在共有部分。友元函式的定義在類體外實現,不需要加類限定。
- 一個類中的成員函式可以是另外一個類的友元函式,而且一個函式可以是多個類友元函式。
- 友元函式可以訪問類中的私有成員和其他資料,但是訪問不可直接使用資料成員,需要通過對物件進行引用。
- 友元函式在呼叫上同一般函式一樣,不必通過對物件進行引用。
- 友元類
- 友元類的所有成員函式都是另一個類的友元函式
- 為什麼對於存在虛擬函式的類中解構函式要定義成虛擬函式
- 因為將派生類物件繫結到基類指標上,銷燬物件時,如果解構函式沒有定義為虛擬函式,則會呼叫基類的解構函式,只能銷燬基類部分的資料,若要呼叫派生類的解構函式,則應該將解構函式定義為虛擬函式,銷燬時通過虛擬函式表找到對應的解構函式
- 解構函式能丟擲異常嗎
- 不能
- 如果解構函式丟擲異常,則異常點之後的程式不會執行,如果解構函式在異常點之後執行了某些必要的動作比如釋放某些資源,則這些動作不會執行,會造成諸如資源洩漏的問題。
- 通常異常發生時,c++的機制會呼叫已經構造物件的解構函式來釋放資源,此時若解構函式本身也丟擲異常,則前一個異常尚未處理,又有新的異常,會造成程式崩潰的問題。
- 建構函式和解構函式中呼叫虛擬函式嗎?
- 不能
- https://www.cnblogs.com/carter2000/archive/2012/04/28/2474960.html
- https://blog.csdn.net/k346k346/article/details/49872023
- 建構函式或者解構函式中呼叫虛擬函式並不會發揮虛擬函式動態繫結的特性
- 即使在建構函式或者解構函式中成功呼叫了虛擬函式,程式的執行結果也是不可控的(在基類中呼叫了派生類的函式)
- 指標和引用的區別
- 指標儲存的是所指物件的地址,引用是所指物件的別名,指標需要通過解引用間接訪問,而引用是直接訪問;
- 指標可以改變地址,從而改變所指的物件,而引用必須從一而終;
- 引用在定義的時候必須初始化,而指標則不需要;
- 指標可以為空,引用不能為空
- 可以有const指標,沒有const引用
- 智慧指標
- https://blog.csdn.net/shuishanga/article/details/52982102
- 智慧指標是一個類,原理是RAII(構造時獲取資源,析構時釋放資源)
- 使用智慧指標需要include<memory>
- 為什麼要使用智慧指標
- 解決記憶體洩漏和野指標這兩個問題
- 記憶體洩漏
- 動態開闢的空間,在使用完畢後未釋放
- 記憶體洩漏是資源洩漏中的一種,資源洩漏的另外一種是控制代碼洩漏
- 控制代碼洩漏
- 舉個例子,socket控制代碼洩漏:B多次嘗試連線A,每一次重連使用一個socket id ,當C連線B的時候,B沒有了可用的socket id,所以B拒絕服務,解決問題的方法是:在B每次重連A的時候,呼叫系統提供的close()函式,把已經斷開連線的socket的socket id釋放
- 控制代碼洩漏
- 野指標
- 未初始化或未清零的指標
- 形成野指標的原因
- 指標變數沒有被初始化
- 指標p被free或者delete之後,沒有置為NULL,讓人誤以為p是個合法的指標(淺拷貝)
- 記憶體洩漏
- 解決記憶體洩漏和野指標這兩個問題
- auto_ptr
- 解決了記憶體洩漏問題和淺拷貝導致的野指標問題
- get()得到原始指標
- reset(引數)重新繫結指向物件,原來的物件被釋放(如果不帶引數,則釋放資源)
- release()把智慧指標賦值為空,但是它原來指向的記憶體並沒有被釋放
- auto_ptr的成員函式時用的是“.”,訪問指向物件的成員時用的是“->”
- 存在的問題
- 所有權轉移(賦值或複製)
- 對智慧指標進行賦值時,如ptest2 = ptest,ptest2會接管ptest原來的記憶體管理權,ptest會變為空指標,如果ptest2原來不為空,則它會釋放原來的資源
- 多個auto_ptr不能同時擁有同一個物件
- Test *t1 = new Test(3); auto_ptr<Test> ptr1(t1); auto_ptr<Test> ptr2(t1);這裡ptr1與ptr2都認為指標t1是歸它管的,在析構時都試圖刪除t1,這樣就造成了重複釋放問題
- 不能用auto_ptr管理陣列指標
- auto_ptr的解構函式中刪除指標用的是delete,而不是delete []
- 不能在stl中使用
- p1=p2,使p2為空,這樣會使得stl容器裡很多元素為空
- 所有權轉移(賦值或複製)
- C++ 11標準中出現的新智慧指標
- unique_ptr
- auto_ptr中的函式仍可用
- move()可以將所有權由一個unique_ptr物件轉移到另一個unique_ptr物件
- 禁止賦值和複製
- 同一時刻只能有一個unique_ptr例項指向給定物件。拷貝建構函式以及等號(“=”)是無法使用的
- 可以管理陣列指標
- 因為unique_ptr有unique_ptr< X[ ] >過載版本,銷燬動態物件時呼叫delete[],所以可以用unique_ptr來管理陣列指標
- 可以在stl容器中使用
- 因為禁止了賦值和複製
- shared_ptr
- shared_ptr是共享所有權的,其內部有一個計數機制
- 預設使用delete實現資源釋放,也可以定義自己的函式來釋放
- 自定義釋放的方法有兩種
- 括號***作符的過載
- lambda表示式(匿名的區域性函式)
- 自定義釋放的方法有兩種
- shared_ptr物件的引用是強引用
- 強引用
- 物件被建立時,計數為1;每建立一個變數引用該物件時,該物件的計數就增加1;當上述變數銷燬時,物件的計數減1,當計數為0時,這個物件也就被析構了
- 弱引用
- 弱引用不修改物件的引用計數,它只是檢測所管理的物件是否已經被釋放
- 強引用
- 存在的問題
- 多個獨立的shared_ptr例項不能共享一個物件(不能將一個物件繫結到多個智慧指標,可以共享所有權,通過=實現),因為可能會重複釋放
- 迴圈引用問題
- 會造成記憶體洩漏
- this指標的問題
- 類的一個成員函式需要傳遞其this指標到一個普通函式,類的物件在主函式裡會繫結到一個智慧指標,在傳遞this的時候又綁定了一個智慧指標,這樣會造成重複釋放。
- weak_ptr
- 解決shared_ptr的迴圈引用和this指標的問題
- 迴圈引用類裡面的shared_ptr改成weak_ptr
- this指標用weak_ptr繫結後通過weak_ptr的lock()來獲取shared_ptr
- 不具有普通指標的行為,它的作用在於協助shared_ptr工作,被設計為與shared_ptr共同工作
- weak_ptr物件的引用是弱引用
- weak_ptr觀測資源,但沒有共享資源,不會修改引用計數
- use_count():觀測資源的引用計數
- expired():等價於use_count()==0,但更快
- lock():獲取shared_ptr,當expired()==true的時候,lock()函式將返回一個儲存空指標的shared_ptr
- 解決shared_ptr的迴圈引用和this指標的問題
- unique_ptr
- private protected public
- private:只能由本類中的函式,友元函式訪問
- protected:可以被本類中的函式,子類的函式,友元函式訪問
- public : 可以被本類函式,子類的函式,類物件,友元函式訪問
- private屬性不能被繼承
- 使用private繼承,父類中protected , public屬性變成private
- 使用protected繼承,父類中的protected,public屬性變成protected
- 使用public繼承,父類中的屬性在子類中不變
- CPP記憶體空間
- 棧
- 由編譯器分配和釋放,存放函式的引數值,區域性變數的值。在一個程序中,位於使用者虛擬地址空間頂部的是使用者棧,編譯器用它來實現函式的呼叫
- 堆
- 由程式設計師分配和釋放,若程式設計師不釋放,則程式結束時被OS回收。存放由new,malloc分配的記憶體,可動態擴充套件和收縮
- 全域性區(靜態區)
- 全域性變數和靜態變數的儲存是放在一起的,初始化的全域性變數和初始化的靜態變數在一塊區域;未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域
- 文字常量區
- 常量字串放在這裡,程式結束後由系統釋放
- 程式程式碼區
- 存放函式的二進位制程式碼
- 堆和棧的區別
- 棧由編譯器管理,堆由程式設計師控制
- 堆會產生碎片,棧不會產生碎片
- 堆是向上(記憶體增加的方向)生長的,棧是向下生長的
- 棧
- 左值和右值
- 左值既能夠出現在等號左邊也能出現在等號右邊的變數(或表示式),右值指的則是隻能出現在等號右邊的變數(或表示式)
- 左值是指表示式結束後依然存在的持久物件,而右值是指表示式結束時就不再存在的臨時物件
- 動態連結庫和靜態連結庫
- https://blog.csdn.net/songjinshi/article/details/7383028
- 靜態連結:在編譯連結的時候將引用庫檔案和自己的檔案一起打包成可執行檔案
- 動態連結:是在程式執行時才被載入
- 靜態連結庫:windows下是.lib,linux下是.a
- 動態連結庫:windows下是.dll,linux下是 .so
- explicit
- 宣告為explicit的建構函式不能在隱式轉換中使用
- C++四種類型轉換
- 記憶體對齊的原則
- 陣列和指標
- https://www.cnblogs.com/fenghuan/p/4775034.html
- 陣列具有確定數量的元素,而指標只是一個標量值
- 行內函數有什麼優點?行內函數與巨集定義的區別?
- 巨集定義在預編譯的時候就會進行巨集替換;
- 行內函數在編譯階段,在呼叫行內函數的地方進行替換,減少了函式的呼叫過程,但是使得編譯檔案變大。因此,行內函數適合簡單函式,對於複雜函式,即使定義了內聯編譯器可能也不會按照內聯的方式進行編譯。
- 行內函數相比巨集定義更安全,行內函數可以檢查引數,而巨集定義只是簡單的文字替換。因此推薦使用行內函數,而不是巨集定義。
- 使用巨集定義函式要特別注意給所有單元都加上括號,#define MUL(a, b) a b,這很危險,正確寫法:#define MUL(a, b) ((a) (b))
- C++記憶體管理
- https://blog.csdn.net/caogenwangbaoqiang/article/details/79788368
- 記憶體洩漏會降低計算機效能
- 解決記憶體洩漏
- 使用智慧指標
- 檢查記憶體洩漏
- https://blog.csdn.net/nec22019/article/details/72950140
- Windows下在debug模式下用CRT庫
- 記憶體分配要通過CRT在執行時實現,只要在分配記憶體和釋放記憶體時分別做好記錄,程式結束時對比分配記憶體和釋放記憶體的記錄就可以確定是不是有記憶體洩漏
- 通過包括 crtdbg.h,將malloc和 free函式對映到它們的除錯版本,即 _malloc_dbg和 _free_dbg,這兩個函式將跟蹤記憶體分配和釋放。 此對映只在除錯版本(在其中定義了_DEBUG)中發生。 釋出版本使用普通的 malloc和 free函式。
- 記憶體分配要通過CRT在執行時實現,只要在分配記憶體和釋放記憶體時分別做好記錄,程式結束時對比分配記憶體和釋放記憶體的記錄就可以確定是不是有記憶體洩漏
- Linux下用valgrind工具
- lambda表示式
- https://www.cnblogs.com/DswCnblog/p/5629165.html
- 匿名函式
- [int a](int b){} :a是在函式內可以訪問的外部變數,b是函式引數,可以通過在函式後面用()傳入引數如:
- [](int a){cout<<a<<endl;}(123)
- STL
- 容器及迭代器使用
- 演算法使用
- 迭代器原理
- https://blog.csdn.net/Dawn_sf/article/details/77929225
- 迭代器是底層封裝一個指標,最後對這個類進行各種各樣的運算子過載(++,==,!=等等). 讓它成為一個擁有指標功能的特殊類(和智慧指標有點像)
- hash_map比map查詢速度快,但是比map需要的記憶體多,是一種用空間換時間的做法
- hash_map使用https://blog.csdn.net/ls1627550352/article/details/52760693
- 必須在建構函式初始化列表裡進行初始化的資料成員有哪些
- const成員
- 引用型別
- 沒有預設建構函式的
- 建構函式中賦值和初始化列表賦值的區別
- 建構函式中賦值,先呼叫預設建構函式,再呼叫拷貝建構函式
- 初始化列表只調用一次拷貝建構函式賦值
- 手寫strcpy
-
char * strcpy( char *strDest, const char *strSrc ) { assert( (strDest != NULL) && (strSrc != NULL) ); if(strlen(strDest)<strlen(strSrc)) return NULL; //標準的strcpy函式沒有此判斷 char *address = strDest; while( (*strDest++ = * strSrc++) != ‘\0’ ); *strDest='\0'; //標準的strcpy函式沒有此***作 return address; }
-
- i++和++i
- i++是先把i的值拿來用,然後在自增1
- ++i是想把i自增1然後拿來用
- 跨平臺技術有哪些
- https://blog.csdn.net/xiangzhihong8/article/details/68067665
- 程式碼轉換
- 將某個語言轉成另一種語言(比如將java轉成c)
- 編譯流
- 將某個語言編譯為二進位制檔案,生成動態庫或打包成 apk/ipa/xap 檔案
- 虛擬機器
- 通過將某個語言的虛擬機器移植到不同平臺上來執行
- 鏈式***作
- 利用運算子進行的連續***作,如連續的賦值,連續的相加
- 運算子優先順序
- to_string()
- 將引用作為函式返回值要注意的地方
- 不能返回區域性變數,因為區域性變數在棧裡面建立,函式呼叫完就會被釋放,所引用的地址就沒有了
- 不能返回new分配的記憶體的引用,因為new了以後沒有delete會造成記憶體洩漏
- 返回引用的好處
- 可以實現連續的輸入輸出賦值等***作(鏈式***作)
- include<>和include“”
- include<>去編譯器的類庫路徑裡面找標頭檔案,include""先在專案的當前路徑裡面找標頭檔案,如果沒找到再去編譯器的類庫路徑裡面找。
- struct和class的區別
- struct預設是public的,class預設是private的
- struct 能包含成員函式嗎,能繼承嗎,能多型嗎?
- 都能
- ifndef/define/endif作用
- 防止重複包含標頭檔案和重複定義巨集
- C++11新特性
- C++相對於C語言的優點
- 資料結構與演算法
- 這部分內容很多一定要多刷牛客
- Hash表
- 二叉樹遍歷(遞迴和非遞迴)
- 二叉查詢樹
- 平衡樹
- https://blog.csdn.net/skyroben/article/details/72824146
- 高度平衡的二叉搜尋樹
- 左子樹和右子樹的高度差不超過1
- 左子樹和右子樹都是平衡樹
- 紅黑樹
- https://blog.csdn.net/yangyutong0506/article/details/78204953
- 常見問題https://blog.csdn.net/gao1440156051/article/details/51581394
- 結點要麼是紅色要麼是黑色
- 根結點永遠是黑色
- 所有葉子結點都是紅色
- 紅色結點的兩個孩子結點都是黑色
- 任意一個結點到其子樹的任意一個葉子結點所經過的黑結點數目是一樣的
- Trie樹(字典樹)
- 海量資料問題
- 排序演算法
- 位運算
- https://blog.csdn.net/fox64194167/article/details/20692645
- 按位取反~
- 翻轉***作數的每一位 每個 1 被設定為 0 而每個 0 被設定為 1。~y=-y-1
- ^異或(模2加)
- 左移***作符 << :從右邊開始用 0 補空位
- 右移***作符 >> :從左邊開始,或者插入符號位的拷貝 或者插入 0
- 按位與&
- 按位異或^
- 按位或 |
- 優先順序:移位符高於邏輯符
- 最大子串問題
-
#include<iostream> #include<string> #include<map> #include<algorithm> using namespace std; int longstr(string s){ int len=s.size(); int pre=0; int max=0; map<char,int> m; int i; for(i=0;i<len;i++){ if(m.find(s[i])!=m.end()){ pre=m[s[i]]+1; } m[s[i]]=i; if(max<(i-pre+1)) max=i-pre+1; } return max; } int main(){ string s; cin>>s; cout<<longstr(s)<<endl; return 0; }
-
- 最大公共子序列
- 各個點之間最短路
- 陣列逆序對
- Bit-map
- https://blog.csdn.net/yanerhao/article/details/72848524
- https://blog.csdn.net/ArchyLi/article/details/78573362
- stl裡面的bitset用法http://www.cppblog.com/ylfeng/archive/2010/03/26/110592.html
- 點陣圖,是實現海量資料處理的常用的方法,用一位表示一個數據(1出現,0沒出現)
- 兔子繁殖
- 斐波那契數列
- 這個月的兔子等於上個月兔子的數量加上上個月可繁殖的兔子(即上上個月的兔子)數量。
- f(n)=f(n-1)+f(n-2)
- 網路與TCP/IP
- TCP與UDP之間的區別
- TCP
- 為什麼是三次握手不是兩次
- 服務端驗證客戶端能收到自己的資訊
- UDP
- HTTP
- https
- https://blog.csdn.net/u014044812/article/details/79571927
- 在應用層和傳輸層之間加了一個ssl或者tls(tls是ssl的升級)
- cookie和session
- https://blog.csdn.net/mym940725/article/details/79159011
- https://blog.csdn.net/qq_35257397/article/details/52967241
- 詳解https://blog.csdn.net/fangaoxin/article/details/6952954
- cookie存放在客戶端,session存放在伺服器端,都是用於會話跟蹤
- 瀏覽器第一次訪問伺服器,伺服器建立一個session,並將session id返回給瀏覽器,瀏覽器將其儲存在cookie裡面
- cookie用來儲存使用者資訊(如賬號密碼)及實現session(儲存session id,每次訪問伺服器的時候都帶上這個session id),要是瀏覽器禁用了cookie則通過url重寫技術來跟蹤會話(url後面被附加上一個諸如 sid=xxxxx 這樣的引數)
- session用來識別使用者
- Cookie有大小限制以及瀏覽器在存cookie的個數也有限制,Session理論上沒有大小限制(伺服器端儲存session的方法很多:比如記憶體,資料庫,檔案)
- Cookie有安全隱患,通過攔截或本地檔案找得到你的cookie後可以進行攻擊。session儲存在伺服器安全一點
- Session儲存在伺服器端一段時間後會消失,如果session過多會增加伺服器的壓力,cookie有效期為正數則為持久化cookie,寫入對應的cookie檔案無論使用者關閉了瀏覽器還是電腦,只要在有效期之前cookie都是有效的,若cookie有效期為負數則為臨時cookie,只在本視窗及本視窗子視窗有效,關閉瀏覽器cookie就消失,預設cookie有效期是-1
- OSI模型中ARP協議屬於鏈路層;TCP/IP模型中,ARP協議屬於網路層
- 瀏覽器中輸入一個URL發生什麼
- https://blog.csdn.net/jeffleo/article/details/77151646
- 首先在應用層進行DNS解析,先從本地DNS快取找,如果沒有找到就訪問DNS伺服器(遞迴和迭代兩種方式)
- 用DNS解析出ip以後在應用層傳送http請求
- 然後在傳輸層tcp三次握手建立連線,然後傳輸資料
- 在網路層使用IP協議來傳輸分割好的tcp資料包資料,使用ARP協議根據ip得到mac地址
- 找到mac地址後把資料傳送到資料鏈路層進行傳輸
- 接受方在資料鏈路層收到資料後把資料一層一層的往上傳,一直傳到應用層
- 然後伺服器響應請求,返回html檔案
- 瀏覽器收到伺服器返回的檔案以後進行頁面渲染
- get和post的區別
- https://blog.csdn.net/qq_26360877/article/details/70665820
- post安全性高,get效率高
- 狀態碼
- 1xx表示請求被接受,需要進一步***作
- 2xx表示請求成功
- 3xx表示需要更多的***作來完成這個請求
- 4xx表示請求失敗
- 5xx表示伺服器內部錯誤
- 流量控制和擁塞避免的區別
- 流量控制是控制傳送方的傳送速度從而使得接收方能正常接收
- 擁塞避免是避免過多的流量進入網路造成網路擁堵
- 資料庫
- SQL語句
- 看MySQL必知必會
- and 的優先順序比 or 要高,其實用的時候加上括號就好了
- 使用萬用字元必須使用like,萬用字元(%0個或多個字元,_一個字元)
- 正則表示式regexp
- \\(匹配)
- 幾乎所有型別的 WHERE 子句都可以用 HAVING 來替代。唯一的差別是WHERE 過濾行,而 HAVING 過濾分組
- 外來鍵是另一個表中的主鍵
- join
- https://blog.csdn.net/huatian5/article/details/80854455
- inner join 內連線,inner可以省略,兩表取交集
- left join 左連線,以左表為基礎,返回右表中匹配的行,若右表中沒有匹配的行則返回NULL
- right join 右連線,以右表為基礎,返回左表中匹配的行,若左表中沒有匹配的行則返回NULL
- 遊標是一種從包括多條資料記錄的結果集中每次提取一條記錄的機制
- 常用語句
- 語句大全
- 50道例題
- 看MySQL必知必會
- MySQL索引結構
- B+樹索引
- Hash索引
- B+樹索引和Hash索引的區別?
- Hash索引等值查詢效率更高,但是Hash索引不支援範圍查詢
- 索引
- https://www.cnblogs.com/shuaiandjun/p/5648020.html
- 索引可以增加檢索效能,同時會降低修改效能
- 索引的作用
- 可以大大加快資料的檢索速度
- 建立唯一性索引,可以保證表中的每一行資料的唯一性
- 加速表和表之間的連線
- 可以減少查詢中分組和排序的時間
- 索引並不是越多越好
- 建立索引和維護索引要耗費時間,資料量越大耗費的時間越多
- 索引需要佔用物理空間
- 對資料進行維護的時候(增加,刪除,修改),索引也要動態維護,這樣就降低了資料的維護速度
- 索引是建立在資料庫表的某些列上面的,一般在需要經常搜素的列上建立索引,很少查詢的列不建立索引(因為不能明顯提高查詢的速度,反而還會因為增加了索引降低了維護的速度和增加了空間的需求),需要經常增加,刪除,修改***作的列也不適合增加索引
- 建立索引 create index
- 索引的特徵(兩個)
- 唯一性索引
- 索引列中的資料是唯一的
- 複合索引
- 索引建立在兩個列或者多個列上
- 唯一性索引
- 聚集索引
- 表記錄的排列順序和與索引的排列順序一致
- 非聚集索引
- 表記錄的排列順序和與索引的排列順序不一致
- 聚集索引在資料庫中開闢一個物理空間存放,非聚集索引看成是一個含有聚集索引的表
- InnoDB與MyISAM區別
myisam提高了查和增加的效率
innodb的功能更全面,但相對來說效率低一些- https://www.cnblogs.com/xfvipp/p/6721470.html
- innodb支援事務支援主鍵不支援全文索引,myisam不支援事務不支援主鍵支援全文索引
- myisam使用的是表鎖(直接鎖定整張表),innodb使用的是行鎖(也支援表鎖)
- myisam在磁碟上儲存成三個檔案(.frm檔案儲存表定義,.MYD是資料檔案,.MYI是索引檔案;innodb則由.frm檔案,表空間和日誌檔案組成。
- myisam內建了一個計算器儲存了表的總行數,innod則沒有。
- myisam只把索引load到記憶體,innodb把索引和資料都load到記憶體
- 什麼時候需要用到事務
- 事務,它是一個***作序列,這些***作要麼都執行,要麼都不執行
- 例如,銀行轉賬工作:從一個賬號扣款並使另一個賬號增款,這兩個***作要麼都執行,要麼都不執行
- 事務的基本要素(ACID)
- 原子性:一個事務中的所有***作要麼全都提交成功,要麼全都失敗回滾
- 一致性:從一個一致的狀態轉到另一個一致的狀態
- 隔離性:一個事務的做的修改,在提交前對其它事務是不可見的
- 永續性:一旦事務提交,所做的修改就會永久儲存在資料庫中
- 事務的四個隔離級別
- 未授權讀取
- 一個事務寫資料,不允許其他事務寫,但允許其他事務讀(解決了更新丟失,存在髒讀的問題)
- 授權讀取
- 一個事務讀資料,允許其他事務訪問資料,但是未提交的寫事務禁止其他事務對該行的訪問(解決了髒讀的問題,可能出現不可重複讀)
- 可重複讀
- 事務讀的時候禁止其他事務寫(但是允許其他事務讀),事務寫的時候禁止其他事務讀寫。解決了不可重複讀,但是可能出現幻讀
- 幻讀
- 事務在***作的時候進行了兩次查詢,第二次查詢出現了第一次沒有的資料或者缺少了第一次出現的資料(其他事務插入或刪除資料造成的)
- 序列化
- 事務只能一個接一個的執行(問題都解決了,但是效能低)
- 未授權讀取
- 更新丟失
- 兩個事物對一行資料更新,一個事務對資料的更新把另一個數據對事務的更新給覆蓋了
- 髒讀
- 一個事務讀取到了另一個事務未提交的資料
- 不可重複讀
- 一個事務對同一行資料讀取兩次得到不一樣的結果
- 鎖
- 共享鎖(讀鎖)
- 加了讀鎖,可以讀不能寫,其他事務還可以對資料物件加讀鎖但是不能加寫鎖
- 排他鎖(寫鎖)
- 加了寫鎖,事務對資料可讀可寫,但是其他事務不能再加任何鎖
- 悲觀鎖
- 顧名思義,就是很悲觀,每次去拿資料都認為別人會修改,所以每次拿資料都會上鎖
- 樂觀鎖
- 顧名思義,就是很樂觀,每次去拿資料都認為別人不會修改,所以每次拿資料都不上鎖,但是在更新的時候會看一下在這期間有沒有人更新過這個資料,如果發現有人修改就會返回錯誤資訊,讓使用者決定如何處理。
- 共享鎖(讀鎖)
- SQL語句
- Linux及***作系統知識
- 程序
- 是程式關於某個資料集合上的一次執行
- 執行緒
- 是程序的一個實體,是程序的一個執行單位
- 程序與執行緒區別
- 程序有自己獨立的地址空間和資源,而執行緒沒有,執行緒必須依賴於程序而存在
- 程序之間不能共享資源,而執行緒共享所在程序的地址空間和其它資源
- 程序是系統資源分配的單位,執行緒是CPU排程的單位
- 執行緒是程序的執行單元
- 一個程式至少有一個程序,一個程序至少有一個執行緒
- 一個執行緒只屬於一個程序,一個程序可以擁有多個執行緒
- 程序切換的開銷較大。執行緒相對較小
- 執行緒間棧和暫存器不能共享,堆和全域性變數以及區域性變數都可以共享
- 執行緒比程序具有哪些優勢
- 什麼時候用多程序?什麼時候用多執行緒?
- Linux中程序和執行緒使用的函式
- 執行緒同步
- https://blog.csdn.net/u010977122/article/details/53106311
- 臨界區
- 保證每次只能有一個執行緒進入臨界區,在幾種同步處理中,臨界區速度最快,但它只能實現同進程中的多個執行緒同步。c++11並沒有為我們提供臨界區類
- 互斥量
- mutex支援多程序。c++11標準庫中提供了mutex類
- 訊號量
- p***作
- 申請資源
- S減1(S為訊號量)
- 若S減1後仍大於等於零,則程序繼續執行;
- 若S減1後小於零,則該程序等待
- 申請資源
- v***作
- 釋放資源
- S加1
- 若相加結果大於零,則程序繼續執行
- 若相加結果小於等於零,喚醒一個等待程序,然後再返回原程序繼續執行或轉入程序排程。
- 釋放資源
- p***作
- 事件(windows裡面)
- 建立事件
- 等待事件被觸發
- WaitForSingleObject(aEvent ,3000);意思就是當代碼執行到這的時候,就會在此處阻塞著,直到另外一個執行緒裡觸發這個事件後或者等待超時後,才會繼續往下執行
- 程序間通訊方式
- 共享檔案對映
- 常見的訊號有哪些
- 記憶體管理
- 虛擬記憶體
- ***作系統層面對記憶體的管理
- 記憶體池的作用
- STL裡記憶體池如何實現
- 程序空間和核心空間對記憶體的管理不同
- Linux的slab層,VAM
- 夥伴演算法
- 高階記憶體
- 程序排程
- 死鎖
- 多個執行緒因競爭資源而造成的一種僵局
- 發生的原因
- 系統資源不足
- 資源分配不當
- 執行緒間推進的順序不當
- 死鎖發生的條件
- 資源獨佔
- 一段時間內資源只能被一個程序佔有
- 保持申請
- 程序在佔有資源的情況下還能繼續申請其它資源
- 不可剝奪
- 申請者不能強行從佔有者手裡剝奪資源
- 迴圈等待
- p1等p2,p2等p3....................pn等p1
- 資源獨佔
- 死鎖的避免
- https://blog.csdn.net/qq_38663729/article/details/80058980
- 設定加鎖順序
- 設定加鎖時限
- 死鎖檢測
- Linux命令
- IO模型
- 執行緒池
- fork與vfork區別
- exit()與_exit()區別
- 孤兒程序與殭屍程序
- Linux是如何避免記憶體碎片的
- 共享記憶體的實現原理
- 同步方法有哪些
- ++i是否是原子***作
- 明顯不是,++i主要有三個步驟,把資料從記憶體放在暫存器上,在暫存器上進行自增,把資料從暫存器拷貝會記憶體,每個步驟都可能被中斷。
- 判斷大小端
- epoll和select,poll
- 設計模式
- 單例模式
class A{ private: A(){a}; static A* a; public: static A* getA(){ if(a==NULL) a=new A(); return a; } }
- 一個類只有一個例項(比如windows的工作管理員,無論你開啟多少次,始終顯示一個視窗)
- 工廠模式
- STL裡的迭代器使用了迭代器模式
- MVC的理解
- 單例模式
- 分散式系統
- map_reduce原理
- 負載均衡
- CDN
- 密碼學
- 對稱加密是加解密都用一個祕鑰
- 非對稱加密分為公鑰和私鑰
- 對稱加密演算法
- DES
- 3DES
- AES
- 非對稱加密演算法
- RSA
- ECC
- Hash演算法
- MD5,SHA-1
- 設計模式
- 程序