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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

【C++】初级面试整理

發布時間:2024/1/18 c/c++ 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++】初级面试整理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C++基礎

四種類型轉換

static_cast:用于良性轉換,一般不會導致意外發生,風險很低。常用于基本類型轉換到 void,轉換父類指針到子類不安全;

const_cast:一般用于去掉const屬性以及volatile,但是如果原來他就是常量去掉之后千萬不要修改;比如你手里有一個常量指針引用,但是函數接口是非常量指針,可能需要轉換一下;成員函數聲明為const,你想用this去執行一個函數,也需要用const_cast;

dynamic_cast:用于在類的繼承層次之間進行類型轉換,它既允許向上轉型(Upcasting),也允許向下轉型(Downcasting)。向上轉型是無條件的,不會進行任何檢測,所以都能成功;向下轉型的前提必須是安全的,要借助 RTTI 進行檢測,所有只有一部分能成功;

reinterpret_cast:非常簡單粗暴,所以風險很高,一般用于跨類型的轉換,如int到void*,用于序列化網絡包數據等。

C++的內存管理

在C++中,內存被分成五個區:棧、堆、自由存儲區、靜態存儲區、常量區

棧:存放函數的參數和局部變量,編譯器自動分配和釋放

堆:new關鍵字動態分配的內存,由程序員手動進行釋放,否則程序結束后,由操作系統自動進行回收

自由存儲區:由malloc分配的內存,和堆十分相似,由對應的free進行釋放

全局/靜態存儲區:存放全局變量和靜態變量

常量區:存放常量,不允許被修改

extern“C”作用

extern "C"的主要作用就是為了能夠正確實現C++代碼調用其他C語言代碼。加上extern "C"后,會指示編譯器這部分代碼按C語言的進行編譯,而不是C++的。也就是C和C++代碼的編譯邏輯是不一樣的,并且C中的全局變量也需要被其他引用的文件識別。

static 的作用域

某一個文件中定義的靜態的變量,則它的作用域是整個文件。與之相對的的是extern!

在.h文件中定義了一個靜態的全局變量x,不同文件為每個包含該頭文件的cpp都創建一個全局變量,但他們都是獨立的,只在該cpp文件共享該變量。所以一般定義static全局變量時,都把它放在cpp文件中而不是頭文件,從而避免多個源文件共享,從而造成不必要的信息污染。

enum枚舉類型和#define宏定義的區別

  • 宏定義沒有類型檢查和安全檢查,所以會導致邊際效應,出現不可預知的錯誤;enum在編譯階段進行類型檢查,但是只能進行整型的定義;
  • 宏定義僅僅是替換和展開,并不進行內存的分配;enum常量存儲在內存數據段的靜態存儲區;
  • define是在預處理階段對所定義的常量進行替換展開;enum是程序運行時起作用;
  • 枚舉常量具有類型,但宏沒有類型;

棧溢出的原因以及解決方法

  • 函數調用層次過深,每調用一次,函數的參數、局部變量等信息就壓一次棧;
  • 局部變量體積太大。解決辦法大致說來也有兩種:
    • 增加棧內存的數目;增加棧內存方法如下,在vc6種依次選擇Project->Setting->Link,在Category中選擇output,在Reserve中輸入16進制的棧內存大小如:0x10000000;
    • 使用堆內存;具體實現由很多種方法可以直接把數組定義改成指針,然后動態申請內存;也可以把局部變量變成全局變量,一個偷懶的辦法是直接在定義前邊加個static,呵呵,直接變成靜態變量(實質就是全局變量)

什么是內存泄漏?面對內存泄漏和指針越界,有哪些方法

動態分配內存所開辟的空間,在使用完畢后未釋放,導致一直占據該內存,即為內存泄漏。

避免內存泄漏方法:

  • 誰開辟誰釋放;
  • 使用智能指針;
  • 指針指向新地址時參考規則;
  • new和delete、new[]和delete[]要對應。

C++中const的作用以及和宏的區別

const修飾的內容不可改變, 定義常量只是一種使用方式,還有const數據成員,const參數, const返回值, const成員函數等, 被const修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。

const相對#define可以做類型校驗,并且分配內存。

既然C++中有更好的const為什么還要使用宏

宏的作用發生在預編譯,const是再編譯階段,所以const無法代替宏作為衛哨來防止文件的重復包含。

對多態的理解

多態按字面的意思就是多種形態。當類之間存在層次結構,并且類之間是通過繼承關聯時,就會用到多態。
C++ 多態意味著調用成員函數時,會根據調用函數的對象的類型來執行不同的函數。

多態是指一個接口多種實現,這是面向對象編程的核心,多態分為以下兩種:

靜態多態:也就是編譯時多態,主要實現方式為重載模板

動態多態:也就是運行時多態,主要實現方式為虛函數 + 繼承

淺拷貝和深拷貝的區別

深拷貝和淺拷貝區別是,在有指針的情況下,淺拷貝只是增加了一個指針指向已經存在的內存,而深拷貝就是增加一個指針并且申請一個新的內存,
使這個增加的指針指向這個新的內存,采用深拷貝的情況下,釋放內存的時候就不會出現在淺拷貝時重復釋放同一內存的錯誤。

C++ 模板

模板是泛型編程的基礎,泛型編程即以一種獨立于任何特定類型的方式編寫代碼。
模板是創建泛型類或函數的藍圖或公式。庫容器,比如迭代器和算法,都是泛型編程的例子,它們都使用了模板的概念。
每個容器都有一個單一的定義,比如 向量,我們可以定義許多不同類型的向量,比如 vector 或 vector 。

STL由什么組成

由容器,迭代器,仿函數,算法,分配器,適配器構成。分配器給容器分配存儲空間,算法通過迭代器獲取容器中的內容,仿函數可以協助算法完成各種操作,配置器用來套接適配仿函數。

STL迭代器的實現原理s

迭代器(iterator)是一種抽象的設計理念,通過迭代器可以在不了解容器內部原理的情況下遍歷容器。除此之外,STL中迭代器一個最重要的作用就是作為容器(vector,list等)與STL算法的粘結劑,只要容器提供迭代器的接口,同一套算法代碼可以利用在完全不同的容器中,這是抽象思想的經典應用。

C++中的容器了解多少

一個容器是特定類型對象的集合,在C++標準庫中包含了大部分常見的容器。STL 是“Standard Template Library”的縮寫,中文譯為“標準模板庫”。STL 是 C++ 標準庫的一部分,不用單獨安裝。TSL核心包括3個組件。容器(containers),算法(algorithms),迭代器(iterators)。除此外還有仿函數,內存配置器和配接器。

  • 序列式容器(Sequence containers):此為可序群集,其中每個元素均有固定位置—取決于插入時機和地點,和元素值無關。如果你以追加方式對一個群集插入六個元素,它們的排列次序將和插入次序一致。STL提供了三個序列式容器:向量(vector)、雙端隊列(deque)、列表(list),此外你也可以把 string 和 array 當做一種序列式容器。
  • 關聯式容器(Associative containers):此為已序群集,元素位置取決于特定的排序準則以及元素值,和插入次序無關。如果你將六個元素置入這樣的群集中,它們的位置取決于元素值,和插入次序無關。STL提供了四個關聯式容器:集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)。

對于容器,主要的操作有:容器的建立、插入元素、刪除元素、查詢、遍歷、計算元素個數、檢查元素是否為空、輸出容器包含的內容。

指針和引用的區別?

指針是一個實體,需要分配內存空間。引用只是變量的別名,不需要分配內存空間。

引用在定義的時候必須進行初始化,并且不能夠改變。指針在定義的時候不一定要初始化,并且指向的空間可變。(注:不能有引用的值不能為NULL)

有多級指針,但是沒有多級引用,只能有一級引用。

指針和引用的自增運算結果不一樣。(指針是指向下一個空間,引用時引用的變量值加1)

sizeof 引用得到的是所指向的變量(對象)的大小,而sizeof 指針得到的是指針本身的大小。

引用訪問一個變量是直接訪問,而指針訪問一個變量是間接訪問。

使用指針前最好做類型檢查,防止野指針的出現;

引用底層是通過指針實現的;

作為參數時也不同,傳指針的實質是傳值,傳遞的值是指針的地址;傳引用的實質是傳地址,傳遞的是變量的地址。

new/delete 與 malloc/free的區別

malloc與free是C語言的標準庫函數, new/delete是C++的運算符, 他們都可以用來申請和釋放內存, malloc和free不在編譯器控制權限之內, 無法調用構造函數和析構函數;而new/delete是由C++編譯器控制的,可以在分配內存之外調用構造函數和析構函數。

new和malloc的區別

new/delete是C++關鍵字,需要編譯器支持。malloc/free是庫函數,需要頭文件支持(stdlib);

使用new操作符申請內存分配時無須指定內存塊的大小,編譯器會根據類型信息自行計算。而malloc則需要顯式地指出所需內存的尺寸。

new操作符內存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無須進行類型轉換,故new是符合類型安全性的操作符。而malloc內存分配成功則是返回void * ,需要通過強制類型轉換將void*指針轉換成我們需要的類型。

new內存分配失敗時,會拋出bac_alloc異常。malloc分配內存失敗時返回NULL。

new會先調用operator new函數,申請足夠的內存(通常底層使用malloc實現)。然后調用類型的構造函數,初始化成員變量,最后返回自定義類型指針。delete先調用析構函數,然后調用operator delete函數釋放內存(通常底層使用free實現)。malloc/free是庫函數,只能動態的申請和釋放內存,無法強制要求其做自定義類型對象構造和析構工作。

new和delete的實現原理, delete是如何知道釋放內存的大小的

new簡單類型直接調用operator new分配內存;而對于復雜結構,先調用operator new分配內存,然后在分配的內存上調用構造函數;對于簡單類型,new[]計算好大小后調用operator new;對于復雜數據結構,new[]先調用operator new[]分配內存,然后在p的前四個字節寫入數組大小n,然后調用n次構造函數,針對復雜類型,new[]會額外存儲數組大小;

new表達式調用一個名為operator new(operator new[])函數,分配一塊足夠大的、原始的、未命名的內存空間;

編譯器運行相應的構造函數以構造這些對象,并為其傳入初始值;

對象被分配了空間并構造完成,返回一個指向該對象的指針。

delete簡單數據類型默認只是調用free函數;復雜數據類型先調用析構函數再調用operator delete;針對簡單類型,delete和delete[]等同。假設指針p指向new[]分配的內存。因為要4字節存儲數組大小,實際分配的內存地址為[p-4],系統記錄的也是這個地址。delete[]實際釋放的就是p-4指向的內存。而delete會直接釋放p指向的內存,這個內存根本沒有被系統記錄,所以會崩潰。

需要在 new [] 一個對象數組時,需要保存數組的維度,C++ 的做法是在分配數組空間時多分配了 4 個字節的大小,專門保存數組的大小,在 delete [] 時就可以取出這個保存的數,就知道了需要調用析構函數多少次了。

解釋下封裝、繼承和多態

封裝:

封裝是實現面向對象程序設計的第一步,封裝就是將數據或函數等集合在一個個的單元中(我們稱之為類)。封裝的意義在于保護或者防止代碼(數據)被我們無意中破壞。

繼承:

繼承主要實現重用代碼,節省開發時間。子類可以繼承父類的一些東西。

多態:

同一操作作用于不同的對象,可以有不同的解釋,產生不同的執行結果。在運行時,可以通過指向基類的指針,來調用實現派生類中的方法。

計算機網絡

TCP 和 UDP 的區別

TCP:傳輸控制協議,全稱 Transmission Control Protocol ,是面向連接、可靠的、基于字節流的傳輸層協議。

UDP:支持無連接的一個傳輸協議,全稱用戶數據報協議(User Datagram Protocol)。UDP為應用程序提供了一種無需建立連接就可發送封裝的數據包的方法。它不提供復雜的機制,只是利用IP來提供面向無連接的一種通信協議。

  • TCP是面向連接的,通過三次握手建立連接,四次揮手解除連接;而UDP是面向無連接的,它發送數據是不需要建立連接的,這樣大大的提高了它的傳輸效率,但是不能確保數據是否完整的傳輸。
  • TCP是一種可靠的通信方式,TCP通過超時重傳、確認應答、擁塞控制等機制來確保數據無差錯、不丟包、不重復且有序;而UDP由于是無連接的,它會以最大的傳輸效率進行數據的傳輸,但不能保證數據傳輸的可靠交付,所以就會出現數據的丟失、重復等問題。
  • TCP首部開銷大占20個字節,而UDP的首部才占8個字節,開銷小
  • TCP協議提供可靠的、面向連接的傳輸服務,一般用于文件的傳輸、郵件的發送以及遠程設備的控制;而UDP無需建立連接,傳輸效率高,不需要接收任何確認回復,可以用于即時的通信,例如QQ或WeChat的語言、視頻通話以及抖音、斗魚等平臺的直播
  • TCP因需要建立連接所以消耗資源大、而UDP不需要建立連接所以消耗資源小
  • 每一條TCP連接只能是點到點的;而UDP不建立連接,所以可以支持一對一,一對多,多對一和多對多的交互通信,也就是可以同時接受多個人的包。

OSI七層模型的簡單介紹

網絡模型不是一開始就有的,在網絡剛發展時,網絡協議是由各互聯網公司自己定義的,各家的協議也是不能互通的。這樣大大的阻礙了互聯網的發展,為了解決這個問題,國際標準化組織 1984 提出的模型標準,簡稱 OSI(Open Systems Interconnection Model)。具體如下圖:

OSI七層模型每一層都有自己的作用,從上到下的作用依次為:

  • 應用層(Application) :提供網絡與用戶應用軟件之間的接口服務
  • 表示層(Presentation) :提供格式化的表示和轉換數據服務,如加密和壓縮
  • 會話層(Session) 提供包括訪問驗證和會話管理在內的建立和維護應用之間通信的機制
  • 傳輸層(Transimission):提供建立、維護和取消傳輸連接功能,負責可靠地傳輸數據(PC)
  • 網絡層(Network): 處理網絡間路由,確保數據及時傳送(路由器)
  • 數據鏈路層(DataLink): 負責無錯傳輸數據,確認幀、發錯重傳等(交換機)
  • 物理層(Physics) :提供機械、電氣、功能和過程特性(網卡、網線、雙絞線、同軸電纜、中繼器)

七層中應用層、表示層和會話層由軟件控制,傳輸層、網絡層和數據鏈路層由操作系統控制,物理層有物理設備控制。

TCP/IP參考模型及協議

模型:TCP/IP 模型是由 OSI 模型演化而來,TCP/IP 模型將 OSI 模型由七層簡化為五層(一開始為四層),應用層、表示層、會話層統一為應用層。

協議:TCP/IP協議被稱為傳輸控制協議/互聯網協議,又稱網絡通訊協議(Transmission Control Protocol)。是由網絡層的IP協議和傳輸層的TCP協議組成,是一個很大的協議集合。

應用層定義了HTTP(超文本傳輸協議)、FTP(文件傳輸協議)、DNS(域名系統)等協議。

傳輸層定義了TCP和UDP(User Datagram Protocol),我們會后面重點介紹一下TCP協議。

網絡層定義了網絡互聯也就是IP協議,主要包括IP、ARP、RARP、ICMP、IGMP。

物理層和數據鏈路層沒有定義任何特定協議,支持所有的標準和專用的協議。

搜索baidu,會用到計算機網絡中的什么層?每層是干什么的

瀏覽器中輸入URL
瀏覽器要將URL解析為IP地址,解析域名就要用到DNS協議,首先主機會查詢DNS的緩存,如果沒有就給本地DNS發送查詢請求。DNS查詢分為兩種方式,一種是遞歸查詢,一種是迭代查詢。如果是迭代查詢,本地的DNS服務器,向根域名服務器發送查詢請求,根域名服務器告知該域名的一級域名服務器,然后本地服務器給該一級域名服務器發送查詢請求,然后依次類推直到查詢到該域名的IP地址。DNS服務器是基于UDP的,因此會用到UDP協議。

得到IP地址后,瀏覽器就要與服務器建立一個http連接。因此要用到http協議,http協議報文格式上面已經提到。http生成一個get請求報文,將該報文傳給TCP層處理,所以還會用到TCP協議。如果采用https還會使用https協議先對http數據進行加密。TCP層如果有需要先將HTTP數據包分片,分片依據路徑MTU和MSS。TCP的數據包然后會發送給IP層,用到IP協議。IP層通過路由選路,一跳一跳發送到目的地址。當然在一個網段內的尋址是通過以太網協議實現(也可以是其他物理層協議,比如PPP,SLIP),以太網協議需要直到目的IP地址的物理地址,有需要ARP協議。

其中:

1、DNS協議,http協議,https協議屬于應用層

應用層是體系結構中的最高層。應用層確定進程之間通信的性質以滿足用戶的需要。這里的進程就是指正在運行的程序。應用層不僅要提供應用進程所需要的信息交換和遠地操作,而且還要作為互相作用的應用進程的用戶代理,來完成一些為進行語義上有意義的信息交換所必須的功能。應用層直接為用戶的應用進程提供服務。

2、TCP/UDP屬于傳輸層

傳輸層的任務就是負責主機中兩個進程之間的通信。因特網的傳輸層可使用兩種不同協議:即面向連接的傳輸控制協議TCP,和無連接的用戶數據報協議UDP。面向連接的服務能夠提供可靠的交付,但無連接服務則不保證提供可靠的交付,它只是“盡最大努力交付”。這兩種服務方式都很有用,備有其優缺點。在分組交換網內的各個交換結點機都沒有傳輸層。

3、IP協議,ARP協議屬于網絡層

網絡層負責為分組交換網上的不同主機提供通信。在發送數據時,網絡層將運輸層產生的報文段或用戶數據報封裝成分組或包進行傳送。在TCP/IP體系中,分組也叫作IP數據報,或簡稱為數據報。網絡層的另一個任務就是要選擇合適的路由,使源主機運輸層所傳下來的分組能夠交付到目的主機。

4、數據鏈路層

當發送數據時,數據鏈路層的任務是將在網絡層交下來的IP數據報組裝成幀,在兩個相鄰結點間的鏈路上傳送以幀為單位的數據。每一幀包括數據和必要的控制信息(如同步信息、地址信息、差錯控制、以及流量控制信息等)。控制信息使接收端能夠知道—個幀從哪個比特開始和到哪個比特結束。控制信息還使接收端能夠檢測到所收到的幀中有無差錯。

5、物理層

物理層的任務就是透明地傳送比特流。在物理層上所傳數據的單位是比特。傳遞信息所利用的一些物理媒體,如雙絞線、同軸電纜、光纜等,并不在物理層之內而是在物理層的下面。因此也有人把物理媒體當做第0層。

請你說一說TCP擁塞控制?以及達到什么情況的時候開始減慢增長的速度?

擁塞控制是防止過多的數據注入網絡,使得網絡中的路由器或者鏈路過載。流量控制是點對點的通信量控制,而擁塞控制是全局的網絡流量整體性的控制。發送雙方都有一個擁塞窗口——cwnd。

1、慢開始

最開始發送方的擁塞窗口為1,由小到大逐漸增大發送窗口和擁塞窗口。每經過一個傳輸輪次,擁塞窗口cwnd加倍。當cwnd超過慢開始門限,則使用擁塞避免算法,避免cwnd增長過大。

2、擁塞避免

每經過一個往返時間RTT,cwnd就增長1。

在慢開始和擁塞避免的過程中,一旦發現網絡擁塞,就把慢開始門限設為當前值的一半,并且重新設置cwnd為1,重新慢啟動。(乘法減小,加法增大)

3、快重傳

接收方每次收到一個失序的報文段后就立即發出重復確認,發送方只要連續收到三個重復確認就立即重傳(盡早重傳未被確認的報文段)。

4、快恢復

當發送方連續收到了三個重復確認,就乘法減半(慢開始門限減半),將當前的cwnd設置為慢開始門限,并且采用擁塞避免算法(連續收到了三個重復請求,說明當前網絡可能沒有擁塞)。

采用快恢復算法時,慢開始只在建立連接和網絡超時才使用。

達到什么情況的時候開始減慢增長的速度?

采用慢開始和擁塞避免算法的時候

  • 一旦cwnd>慢開始門限,就采用擁塞避免算法,減慢增長速度
  • 一旦出現丟包的情況,就重新進行慢開始,減慢增長速度

采用快恢復和快重傳算法的時候

  • 一旦cwnd>慢開始門限,就采用擁塞避免算法,減慢增長速度
  • 一旦發送方連續收到了三個重復確認,就采用擁塞避免算法,減慢增長速度

為什么連接的時候是三次握手

剛開始客戶端處于 closed 的狀態,服務端處于 listen 狀態。然后

第一次握手:客戶端給服務端發一個 SYN 報文,并指明客戶端的初始化序列號 ISN?。此時客戶端處于 SYN_Send 狀態。

第二次握手:服務器收到客戶端的 SYN 報文之后,會以自己的 SYN 報文作為應答,并且也是指定了自己的初始化序列號 ISN(s),同時會把客戶端的 ISN + 1 作為 ACK 的值,表示自己已經收到了客戶端的 SYN,此時服務器處于 SYN_RCVD 的狀態。

第三次握手:客戶端收到 SYN 報文之后,會發送一個 ACK 報文,當然,也是一樣把服務器的 ISN + 1 作為 ACK 的值,表示已經收到了服務端的 SYN 報文,此時客戶端處于 established 狀態。

服務器收到 ACK 報文之后,也處于 established 狀態,此時,雙方以建立起了鏈接。

三次握手的作用

三次握手的作用也是有好多的,多記住幾個,保證不虧。例如:

1、確認雙方的接受能力、發送能力是否正常。

2、指定自己的初始化序列號,為后面的可靠傳送做準備。

關閉的時候卻是四次揮手

剛開始雙方都處于 establised 狀態,假如是客戶端先發起關閉請求,則:

第一次揮手:客戶端發送一個 FIN 報文,報文中會指定一個序列號。此時客戶端處于FIN_WAIT1狀態。

第二次揮手:服務端收到 FIN 之后,會發送 ACK 報文,且把客戶端的序列號值 + 1 作為 ACK 報文的序列號值,表明已經收到客戶端的報文了,此時服務端處于 CLOSE_WAIT狀態。

第三次揮手:如果服務端也想斷開連接了,和客戶端的第一次揮手一樣,發給 FIN 報文,且指定一個序列號。此時服務端處于 LAST_ACK 的狀態。

第四次揮手:客戶端收到 FIN 之后,一樣發送一個 ACK 報文作為應答,且把服務端的序列號值 + 1 作為自己 ACK 報文的序列號值,此時客戶端處于 TIME_WAIT狀態。需要過一陣子以確保服務端收到自己的 ACK 報文之后才會進入 CLOSED 狀態。

服務端收到 ACK 報文之后,就處于關閉連接了,處于 CLOSED 狀態。

TCP ,UDP協議屬于哪一層

傳輸層。

HTTP協議屬于哪一層?IP協議屬于哪一層

應用層;網絡層。

操作系統

進程和線程的區別

  • 進程是資源分配的最小單位,而線程是 CPU 調度的最小單位;
  • 創建進程或撤銷進程,系統都要為之分配或回收資源,操作系統開銷遠大于創建或撤銷線程時的開銷;
  • 不同進程地址空間相互獨立,同一進程內的線程共享同一地址空間。一個進程的線程在另一個進程內是不可見的;
  • 進程間不會相互影響,而一個線程掛掉將可能導致整個進程掛掉;

并發和并行有什么區別

  • 并發(concurrency):把任務在不同的時間點交給處理器進行處理。在同一時間點,任務并不會同時運行。
  • 并行(parallelism):把每一個任務分配給每一個處理器獨立完成。在同一時間點,任務一定是同時運行。

進程間通信方式有哪些?

進程間通信(IPC,InterProcess Communication)是指在不同進程之間傳播或交換信息。IPC 的方式通常有管道(包括無名管道和命名管道)、消息隊列、信號量、共享存儲、Socket、Streams 等。其中 Socket 和 Streams 支持不同主機上的兩個進程 IPC。

管道

  • 它是半雙工的,具有固定的讀端和寫端;
  • 它只能用于父子進程或者兄弟進程之間的進程的通信;
  • 它可以看成是一種特殊的文件,對于它的讀寫也可以使用普通的 read、write 等函數。但是它不是普通的文件,并不屬于其他任何文件系統,并且只存在于內存中。
  • 命名管道

  • FIFO 可以在無關的進程之間交換數據,與無名管道不同;
  • FIFO 有路徑名與之相關聯,它以一種特殊設備文件形式存在于文件系統中。
  • 消息隊列

  • 消息隊列,是消息的鏈接表,存放在內核中。一個消息隊列由一個標識符 ID 來標識;
  • 消息隊列是面向記錄的,其中的消息具有特定的格式以及特定的優先級;
  • 消息隊列獨立于發送與接收進程。進程終止時,消息隊列及其內容并不會被刪除;
  • 消息隊列可以實現消息的隨機查詢,消息不一定要以先進先出的次序讀取,也可以按消息的類型讀取。
  • 信號量

  • 信號量(semaphore)是一個計數器。用于實現進程間的互斥與同步,而不是用于存儲進程間通信數據;
  • 信號量用于進程間同步,若要在進程間傳遞數據需要結合共享內存;
  • 信號量基于操作系統的 PV 操作,程序對信號量的操作都是原子操作;
  • 每次對信號量的 PV 操作不僅限于對信號量值加 1 或減 1,而且可以加減任意正整數;
  • 支持信號量組。
  • 共享內存

  • 共享內存(Shared Memory),指兩個或多個進程共享一個給定的存儲區;
  • 共享內存是最快的一種 IPC,因為進程是直接對內存進行存取。
  • 什么是死鎖?死鎖產生的條件?

    死鎖,是指多個進程在運行過程中因爭奪資源而造成的一種僵局,當進程處于這種僵持狀態時,若無外力作用,它們都將無法再向前推進。 如下圖所示:如果此時有一個線程 A,已經持有了鎖 A,但是試圖獲取鎖 B,線程 B 持有鎖 B,而試圖獲取鎖 A,這種情況下就會產生死鎖。

    • 互斥條件:一個資源每次只能被一個進程使用。
    • 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
    • 不剝奪條件:進程已獲得的資源,在未使用完之前,不能強行剝奪。
    • 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。

    如何解決線程死鎖?

    如果發生了死鎖,那么只要破壞死鎖 4 個必要條件之一中的任何一個,死鎖問題就能被解決。

    如果想要打破互斥條件,需要允許進程同時訪問某些資源,這種方法受制于實際場景,不太容易實現條件;

    打破不可搶占條件,這樣需要允許進程強行從占有者那里奪取某些資源,或者簡單一點理解,占有資源的進程不能再申請占有其他資源,必須釋放手上的資源之后才能發起申請,這個其實也很難找到適用場景;

    進程在運行前申請得到所有的資源,否則該進程不能進入準備執行狀態。這個方法看似有點用處,但是它的缺點是可能導致資源利用率和進程并發性降低;

    避免出現資源申請環路,即對資源事先分類編號,按號分配。這種方式可以有效提高資源的利用率和系統吞吐量,但是增加了系統開銷,增大了進程對資源的占用時間。

    如果我們在死鎖檢查時發現了死鎖情況,那么就要努力消除死鎖,使系統從死鎖狀態中恢復過來。消除死鎖的幾種方式:

    最簡單、最常用的方法就是進行系統的重新啟動,不過這種方法代價很大,它意味著在這之前所有的進程已經完成的計算工作都將付之東流,包括參與死鎖的那些進程,以及未參與死鎖的進程;

    撤消進程,剝奪資源。終止參與死鎖的進程,收回它們占有的資源,從而解除死鎖。這時又分兩種情況:一次性撤消參與死鎖的全部進程,剝奪全部資源;或者逐步撤消參與死鎖的進程,逐步收回死鎖進程占有的資源。一般來說,選擇逐步撤消的進程時要按照一定的原則進行,目的是撤消那些代價最小的進程,比如按進程的優先級確定進程的代價;考慮進程運行時的代價和與此進程相關的外部作業的代價等因素;

    進程回退策略,即讓參與死鎖的進程回退到沒有發生死鎖前某一點處,并由此點處繼續執行,以求再次執行時不再發生死鎖。雖然這是個較理想的辦法,但是操作起來系統開銷極大,要有堆棧這樣的機構記錄進程的每一步變化,以便今后的回退,有時這是無法做到的

    算法

    快速排序的實現原理

    快速排序使用分治法(Divide and conquer)策略來把一個串行(list)分為兩個子串行(sub-lists)。

    // // Created by mxz on 2022/12/19. //#include<iostream>using namespace std;/*** 嚴蔚敏《數據結構》標準分割函數** @param A* @param low* @param high* @return*/ int Paritition1(int A[], int low, int high) {int pivot = A[low];while (low < high) {while (low < high && A[high] >= pivot) {--high;}A[low] = A[high];while (low < high && A[low] <= pivot) {++low;}A[high] = A[low];}A[low] = pivot;return low; }void QuickSort(int A[], int low, int high) //快排母函數 {if (low < high) {int pivot = Paritition1(A, low, high);QuickSort(A, low, pivot - 1);QuickSort(A, pivot + 1, high);} }int main() {int A[] = {2, 5, 1, 3, 4, 10};QuickSort(A, 0, sizeof(A) / sizeof(A[0]));for (int num: A) {cout << num << " ";}return 0; }

    總結

    以上是生活随笔為你收集整理的【C++】初级面试整理的全部內容,希望文章能夠幫你解決所遇到的問題。

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