天天看點

c++ 背景伺服器開發面試題目總結

文章目錄

    • 1 C++ 中include頭檔案時尖括号與雙引号的差別
      • 1.1 差別
      • 1.2 總結
    • 2 c++的封裝 繼承 多态
    • 3 計算機網絡的OSI七層模型,每一層的作用是啥
    • 4 紅黑樹的基本問題
    • 5 set怎麼保證插入不重複的性質
    • 6 一次網頁的通路從URL開始,說一下整個通路的過程
    • 7 TCP和UDP協定的差別
    • 7.1 TCP粘包問題
    • 8 、三次握手協定的具體過程 斷開連接配接是四次揮手的情況
      • 8.1 Tcp的四次揮手 timewait怎麼解釋(詳細一點)
      • 8.2 三次握手之後,雙方怎麼知道後續不會丢包
    • 9 資料庫的事務隔離級别
      • 9.1 第三個級别怎麼解決的 不可重複讀的問題的
    • 10 HTTP協定和HTTPS協定的差別(HTTP是應用層的協定)
    • 11 c++記憶體的五個存儲器以及各自的作用
    • 12 一個表,name,subject,score,找出來所有科目都及格的學生名字
    • 13 資料庫的索引 聚集索引和非聚集索引,聚簇索引 稀疏索引 稠密索引
    • 14 list和vector的差別
      • vector資料結構
      • list資料結構
    • 15 記憶體對齊
      • 之是以要記憶體對齊,有兩方面的原因:
    • 16 c++之中的map的種類
    • 17 namespace介紹一下:命名空間
    • 18 C++記憶體溢出和記憶體洩漏?
    • 19 B類位址 子網路遮罩 255.255.255.248 有多少台主機
    • 20 程序排程算法(作業排程算法)
    • 21 vector的和數組一樣連續存儲,vector的擴容機制
    • 22 c++中 const 和define 的差別的
    • 23 引用和指針的差別
    • 24 static_cast以及 c++之中的類型轉換
    • 25 STL的map和set的差別 低層用啥實作的
    • 26 STL的了解,STL的優勢
    • 27 c++智能指針
    • 28 虛函數和純虛函數
    • 29 哈希表,哈希沖突 解決辦法。
    • 30 線程的生命周期(開始 就緒 結束。。。。。)
    • 31 構造函數和析構函數的子類基類調用順序
    • 32 Mysql的底層引擎是什麼了解嗎 innodb索引的b+樹
    • 33 程序間的通信方式
    • 34 線程的同步方式
      • 34.1 線程同步鎖的種類
      • 34.2 線程建立的基本方式
      • 34.3 線程安全問題
    • 35 程序和線程的差別,多程序和多線程程式設計概念
      • 35.1 什麼是線程安全的
    • 36 使用者态和核心态
    • 37 大資料之中資料的數目是n 選擇第k大的資料 (堆排序),時間複雜度是啥?(n-k)O(logk)?
    • 38 int (*s[10])(int) s是一個什麼資料類型
    • 39 寫一個函數指針 類似(void)func(這裡應該怎麼寫的)
    • 40 SQL語句之中的 delete和 drop的不同
    • 41 作業系統中的虛拟記憶體 :硬碟一部分
    • 42 作業系統條件變量
    • 42.1 作業系統:寫一個生産者,消費者的循環隊列 P V原語句
    • 43 TCP擁塞控制怎麼進行
    • 44 linux的記憶體管理(段頁方式)
    • 45 關系型資料庫和非關系型資料庫額差別
    • 46 c++幾組比較
      • 46.1 c++之中define vs const
      • 46.2 private 和 protect:
      • 46.3 struct vs union
      • 46.4 友元函數,運算符重載
    • 47 vector的擴容機制 以及 vector中push_back操作時間複雜度分析
    • 48 B樹(B-)、B+樹,B*樹的簡單介紹
    • 49 memcpy和strcpy的差別
    • 50 經典面試題之new和malloc的差別
    • 51 面向對象的特征并簡述
    • 52 如何避免死鎖
    • 53 c++類的加載過程
    • 54 MySQL 添加列,修改列,删除列
    • 55 C語言和c++的差別
      • C語言中struct和union的差別是什麼?
      • C和C++中struct的差別是什麼?
    • C++中的 struct與class的差別是什麼?
    • 56 C++中基類的析構函數不是虛函數,會帶來什麼問題
    • 57 頭檔案中的ifndef/define/endif有什麼作用
    • 58 面試題:char * strcpy(char * strDest,const char * strSrc);
    • 59 循環隊列的存儲空間為 Q(1:50) ,初始狀态為 front=rear=50 。經過一系列正常的入隊與退隊操作後, front=rear=25 ,此後又插入一個元素,則循環隊列中的元素個數為( )
    • 60 樂觀鎖與悲觀鎖的差別
    • 61 static
    • 62 map的插入的傳回值是啥
    • 64 io複用問題
    • 65 動态連結和靜态連結
    • 66 map低層紅黑樹的實作
    • 67自定義 結構體作為 map的key 需要注意什麼呢
    • 68 SQL語句之中的内連接配接,外連接配接
    • 69 線程池的介紹

1 C++ 中include頭檔案時尖括号與雙引号的差別

1.1 差別

系統自帶的頭檔案用尖括号括起來,表示編譯器先在使用者的工作目錄下搜尋頭檔案,如果搜尋不到則到系統預設目錄下去尋找,是以雙引号一般用于包含使用者自己編寫的頭檔案。如:#include “student.h” , #include “XXXX.h” 。

使用者自定義的檔案用雙引号括起來,編譯器首先會在使用者目錄下查找,然後在到C++安裝目錄(比如VC中可以指定和修改庫檔案查找路徑,Unix和Linux中可以通過環境變量來設定)中查找。是以一般尖括号用于包含标準庫檔案,如:#include <stdio.h>, #include<stdlib.h>

1.2 總結

  1. 使用 “xxx.h”,告訴編譯器,從目前工作目錄開始查找。
  2. 使用<xxx.h>,告訴編譯器,從系統預設目錄中去查找;
  3. 當不确定的時候,就使用雙引号,系統會從目前工作目錄找完成後,然後再去系統預設目錄中查找。若 #include “” 查找成功,則遮蔽 #include <> 所能找到的同名檔案;否則再按照 #include <> 的方式查找檔案。另外标準庫頭檔案都放在 #include <> 所查找的位置。

2 c++的封裝 繼承 多态

https://blog.csdn.net/ruyue_ruyue/article/details/8211809

3 計算機網絡的OSI七層模型,每一層的作用是啥

https://blog.csdn.net/weixin_34179762/article/details/88729259

計算機網絡——五層與七層模型

https://www.cnblogs.com/qishui/p/5428938.html

c++ 背景伺服器開發面試題目總結

4 紅黑樹的基本問題

https://www.jianshu.com/p/e136ec79235c

紅黑樹是一種含有紅黑結點并能自平衡的二叉查找樹。它必須滿足下面性質:

性質1:每個節點要麼是黑色,要麼是紅色。

性質2:根節點是黑色。

性質3:每個葉子節點(NIL)是黑色。

性質4:每個紅色結點的兩個子結點一定都是黑色。

性質5:任意一結點到每個葉子結點的路徑都包含數量相同的黑結點。

5 set怎麼保證插入不重複的性質

https://zhuanlan.zhihu.com/p/83567235

提供疊代器通路元素,但是無法使用疊代器改變元素值,因為 key就是 value,set的元素必須獨一無二,是以 insert 用的是 rb_tree 的 insert_unique() 函數。multiset 元素的 key 可以重複。是以 insert 用的是 rb_tree 的insert_equal() 函數。

6 一次網頁的通路從URL開始,說一下整個通路的過程

用戶端擷取URL - > DNS解析 - > TCP連接配接 - >發送HTTP請求 - >伺服器處理請求 - >傳回封包 - >浏覽器解析渲染頁面 - > TCP斷開連接配接

通路一個URL經曆了哪些過程

7 TCP和UDP協定的差別

兩者最大的不同就是 TCP 提供可靠的傳輸,而 UDP 提供的是不可靠傳輸

UDP能夠進行廣播

https://blog.csdn.net/zhang6223284/article/details/81414149

TCP 和 UDP 的差別
  • TCP 是面向連接配接的,UDP 是面向無連接配接的
  • UDP程式結構較簡單
  • TCP 是面向位元組流的,UDP 是基于資料報的
  • TCP 保證資料正确性,UDP 可能丢包
  • TCP 保證資料順序,UDP 不保證

TCP 的順序問題,丢包問題,流量控制都是通過滑動視窗來解決的,擁塞控制時通過擁塞視窗來解決的

什麼是面向連接配接,什麼是面向無連接配接

在互通之前,面向連接配接的協定會先建立連接配接,如 TCP 有三次握手,而 UDP 不會

TCP 為什麼是可靠連接配接
  • 通過 TCP 連接配接傳輸的資料無差錯,不丢失,不重複,且按順序到達。
  • TCP 封包頭裡面的序号能使 TCP 的資料按序到達
  • 封包頭裡面的确認序号能保證不丢包,累計确認及逾時重傳機制
  • TCP 擁有流量控制及擁塞控制的機制

7.1 TCP粘包問題

https://my.oschina.net/u/4269462/blog/3195211

https://www.cnblogs.com/findumars/p/7486665.html

github的文章 和這個題目無關的

8 、三次握手協定的具體過程 斷開連接配接是四次揮手的情況

8.1 Tcp的四次揮手 timewait怎麼解釋(詳細一點)

https://blog.csdn.net/chrise_/article/details/80449028

https://blog.csdn.net/qq_38950316/article/details/81087809

8.2 三次握手之後,雙方怎麼知道後續不會丢包

滑動視窗協定

9 資料庫的事務隔離級别

9.1 第三個級别怎麼解決的 不可重複讀的問題的

解決可重複讀的方法

有兩個政策可以防止這個問題的發生:

(1) 推遲事務2的執行,直至事務1送出或者回退。這種政策在使用鎖時應用。

(2) 而在多版本并行控制中,事務2可以被先送出。而事務1,繼續執行在舊版本的資料上。當事務1終于嘗試送出時,資料庫會檢驗它的結果是否和事務1、事務2順序執行時一樣。如果是,則事務1送出成功。如果不是,事務1會被回退。

參考連結:https://www.cnblogs.com/balfish/p/8298296.html

資料庫中的事務,事務的隔離級别

10 HTTP協定和HTTPS協定的差別(HTTP是應用層的協定)

https://www.cnblogs.com/sueyyyy/p/12012570.html

https://blog.csdn.net/xiaoming100001/article/details/81109617

HTTPS和HTTP的差別主要如下:

1、https協定需要到ca申請證書,一般免費證書較少,因而需要一定費用。

2、http是超文本傳輸協定,資訊是明文傳輸,https則是具有安全性的ssl加密傳輸協定。

3、http和https使用的是完全不同的連接配接方式,用的端口也不一樣,前者是80,後者是443。

4、http的連接配接很簡單,是無狀态的;HTTPS協定是由SSL+HTTP協定建構的可進行加密傳輸、身份認證的網絡協定,比http協定安全。

11 c++記憶體的五個存儲器以及各自的作用

https://blog.csdn.net/zou_albert/article/details/107914264

在C++中,記憶體分成5個區,他們分别是堆、棧、自由存儲區、全局/靜态存儲區和常量存儲區。

  • 棧:就是那些由編譯器 在需要的時候配置設定,在不需要的時候自動清除變量 的存儲區。裡面的變量通常是局部變量、函數參數等。
  • 堆:就是那些由new配置設定的記憶體塊,他們的釋放編譯器不去管,由我們的應用程式去控制,一般一個new就要對應一個delete。如果程式員沒有釋放掉, 那麼在程式結束後,作業系統會自動回收。 程式員需要自動釋放堆的記憶體。
  • 自由存儲區:就是那些由malloc等配置設定的記憶體塊,他和堆是十分相似的, 不過它是用free來結束自己的生命的。
  • 全局/靜态存儲區,全局變量和靜态變量被配置設定到同一塊記憶體中,在以前的C語言中,全局變量又分為初始化的和未初始化的(初始化的全局變量和靜态變量在一塊區域,未初始化的全局變量與靜态變量在相鄰的另一塊區域,同時未被初始化的對象存儲區可以通過void*來通路和操縱,程式結束後由系統自行釋放),在C++裡面沒有這個區分了,他們共同占用同一塊記憶體區。
  • 常量存儲區:這是一塊比較特殊的存儲區,他們裡面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改)

12 一個表,name,subject,score,找出來所有科目都及格的學生名字

SELECT DISTINCT A.name FROM Student A 
WHERE A.name not in(
SELECT Distinct S.name FROM Student S WHERE S.score <80)
           

13 資料庫的索引 聚集索引和非聚集索引,聚簇索引 稀疏索引 稠密索引

MySQL (8) 聚集索引 非聚集索引 聚簇索引 稀疏索引 稠密索引

14 list和vector的差別

vector資料結構

vector和數組類似,擁有一段連續的記憶體空間,并且起始位址不變。

是以能高效的進行随機存取,時間複雜度為o(1);

但因為記憶體空間是連續的,是以在進行插入和删除操作時,會造成記憶體塊的拷貝,時間複雜度為o(n)。

另外,當數組中記憶體空間不夠時,會重新申請一塊記憶體空間并進行記憶體拷貝。

list資料結構

list是由雙向連結清單實作的,是以記憶體空間是不連續的。

隻能通過指針通路資料,是以list的随機存取非常沒有效率,時間複雜度為o(n);

但由于連結清單的特點,能高效地進行插入和删除。

與其他序列式容器相比,list和forward_list最大的缺陷是不支援任意位置的随機通路,比如:要通路list 的第6個元素,必須從已知的位置(比如頭部或者尾部)疊代到該位置。

deque是一個double-ended queue,它的具體實作不太清楚,但知道它具有以下兩個特點:

它支援[]操作符,也就是支援随即存取,并且和vector的效率相差無幾,它支援在兩端的操作:push_back,push_front,pop_back,pop_front等,并且在兩端操作上與list的效率也差不多。

15 記憶體對齊

之是以要記憶體對齊,有兩方面的原因:

  • 平台原因:各個硬體平台對存儲空間的處理上有很大的不同。一些平台對某些特定類型的資料隻能從某些特定位址開始存取。————- 比如,有些架構的CPU在通路 一個沒有進行對齊的變量的時候會發生錯誤,那麼在這種架構下程式設計必須保證位元組對齊。
  • 性能原因:記憶體對齊可以提高存取效率。————- 比如,有些平台每次讀都是從偶位址開始,如果一個int型(假設為32位系統)如果存放在偶位址開始的地方,那麼一個讀周期就可以讀出這32bit,而如果存放在奇位址開始的地方,就需要2個讀周期,并對兩次讀出的結果的高低位元組進行拼湊才能得到該32bit資料。

    https://songlee24.github.io/2014/09/20/memory-alignment/

    c++ 背景伺服器開發面試題目總結
struct Q{
    char c;
    int num1;
    double num2;
};
           
struct
{
    int i;    // 4個位元組
    char c1;  // 1個位元組
    char c2;  // 1個位元組
}x1;

struct
{
    char c1;  // 1個位元組
    int i;    // 4個位元組
    char c2;  // 1個位元組
}x2;

struct
{
    char c1;  // 1個位元組
    char c2;  // 1個位元組
    int i;    // 4個位元組
}x3;

int main()
{
    printf("%d\n",sizeof(x1));  // 輸出8
    printf("%d\n",sizeof(x2));  // 輸出12
    printf("%d\n",sizeof(x3));  // 輸出8
    return 0;
}
           

問上述代碼中sizeof(Q)為多少? 16 實際上這是考察struct結構位址對齊的問題

struct的對其系數和以下幾個關系有關

  • 元素大小
  • 元素順序
  • #pargma pack參數

https://www.cnblogs.com/zhao-zongsheng/p/9099603.html

c++ 背景伺服器開發面試題目總結

對齊規則

  • struct中成員在記憶體中按順序排列,在沒有#pargma pack(n)的情況下,各個成員的對齊系數為自己的長度
  • 在有#pargma pack(n)的情況下,各個成員的對齊系數為min(自己的長度,n)

    struct整體的對齊系數為對齊系數中最大的

  • 依次排列時要滿足位址對對齊系數取模為0

16 c++之中的map的種類

  • map是一類關聯式容器,不允許重複的鍵值。它的特點是增加和删除節點對疊代器的影響很小,除了操作節點,對其他的節點都沒有什麼影響。對于疊代器來說,不可以修改鍵值,隻能修改其對應的實值 低層使用紅黑樹實作的,
  • unorder_map與map不同:map的KEY值是有序的,而unorder_map則是無序的,unordered_map的底層是一個防備援的哈希表(開鍊法避免位址沖突)
  • multimap 和 map 的唯一差别是:元素可以重複,也就是 multimap 允許其元素擁有相同的 key。
  • hash_map 和unorder_map類似,前者的空間複雜度最低。

17 namespace介紹一下:命名空間

https://blog.csdn.net/liitdar/article/details/80337871

最典型的例子就是std命名空間,C++标準庫中所有辨別符都包含在該命名空間中

https://blog.csdn.net/lx_392754/article/details/52220676

18 C++記憶體溢出和記憶體洩漏?

1、記憶體溢出

記憶體溢出是指程式在申請記憶體時沒有足夠的記憶體空間供其使用。原因可能如下:

(1)記憶體中加載的資料過于龐大;

(2)代碼中存在死循環;

(3)遞歸調用太深,導緻堆棧溢出等;

(4)記憶體洩漏最終導緻記憶體溢出;

2、記憶體洩漏

記憶體洩漏是指使用new申請記憶體, 但是使用完後沒有使用delete釋放記憶體,導緻占用了有效記憶體。

https://www.cnblogs.com/outs/p/8964941.html

https://blog.csdn.net/invisible_sky/article/details/78205461

添加連結描述C++面試常見題目4_記憶體管理,記憶體洩露

記憶體洩漏的幾種情況

19 B類位址 子網路遮罩 255.255.255.248 有多少台主機

根據子網路遮罩計算最大主機數,廣播位址

計算機網絡——子網劃分(内含習題講解)

20 程序排程算法(作業排程算法)

常用的作業系統程序(作業)排程算法

21 vector的和數組一樣連續存儲,vector的擴容機制

22 c++中 const 和define 的差別的

const 與 #define 差別

  • 定義常量角度: const 定義的常數是變量也帶類型, #define 定義的隻是個常數 不帶類型。
  • 就起作用的階段而言:define是在編譯的預處理階段起作用,而const是在編譯、運作的時候起作用。
  • 就起作用的方式而言: define隻是簡單的字元串替換,沒有類型檢查。而const有對應的資料類型,是要進行判斷的,可以避免一些低級的錯誤,例如:正因為define隻是簡單的字元串替換會導緻邊界效應,具體舉例可以參考下面代碼:
#define N 2+3 //我們預想的N值是5,我們這樣使用N
double a = N/2;  //我們預想的a的值是2.5,可實際上a的值是3.5
           
  • 占用空間而言:
#define PI 3.14     //預處理後 占用代碼段空間
const float PI=3.14;    //本質上還是一個 float,占用資料段空間
           
  • 從是否可以再定義的角度而言: const不足的地方,是與生俱來的,const不能重定義,而#define可以通過#undef取消某個符号的定義,再重新定義。
  • 從代碼調試的友善程度而言: const常量可以進行調試的,define是不能進行調試的,因為在預編譯階段就已經替換掉了。
  • 是否可以做函數參數:宏定義不能作為參數傳遞給函數,const常量可以在函數的參數清單中出現

23 引用和指針的差別

空初大小多變const

  • 空:指針有自己的一塊空間,而引用隻是一個别名;
  • 初:指針可以被初始化為NULL,而引用必須被初始化且必須是一個已有對象 的引用;
  • 大小:使用sizeof看一個指針的大小是4,而引用則是被引用對象的大小;
  • 多:指針可以有多級指針(p),而引用至多一級;
  • 變:指針在使用中可以指向其它對象,但是引用隻能是一個對象的引用,不能 被改變;
  • 可以有const指針,但是沒有const引用;

    https://blog.csdn.net/will130/article/details/48730725

24 static_cast以及 c++之中的類型轉換

C++中四種類型轉換是:static_cast, dynamic_cast, const_cast, reinterpret_cast

1、const_cast

用于将const變量轉為非const

2、static_cast

用于各種隐式轉換,比如非const轉const,void*轉指針等, static_cast能用于多态向上轉化,如果向下轉能成功但是不安全,結果未知;

3、dynamic_cast

用于動态類型轉換。隻能用于含有虛函數的類,用于類層次間的向上和向下轉化。隻能轉指針或引用。向下轉化時,如果是非法的對于指針傳回NULL,對于引用抛異常。要深入了解内部轉換的原理。

向上轉換:指的是子類向基類的轉換

向下轉換:指的是基類向子類的轉換

它通過判斷在執行到該語句的時候變量的運作時類型和要轉換的類型是否相同來判斷是否能夠進行向下轉換。

4、reinterpret_cast

幾乎什麼都可以轉,比如将int轉指針,可能會出問題,盡量少用;

5、為什麼不使用C的強制轉換?

C的強制轉換表面上看起來功能強大什麼都能轉,但是轉化不夠明确,不能進行錯誤檢查,容易出錯。

https://www.jianshu.com/p/1a2310f1b58e

25 STL的map和set的差別 低層用啥實作的

26 STL的了解,STL的優勢

STL的優點:

1.實作資料結構和算法的分離,使得STL非常通用。

2.STL具有高可重用性,高性能,高移植性,誇平台的優點。

  • 高可重用性:STL中幾乎所有的代碼都采用了模闆類和模闆函數的方式實作,代碼重用性高。
  • 高性能:如map,采用紅黑數的變體實作,效率高。
  • 高移植性:STL子產品很容易移植。

27 c++智能指針

C++裡面的四個智能指針: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中後三個是c++11支援,并且第一個已經被11棄用。

為什麼要使用智能指針:

智能指針的作用是管理一個指針,因為存在以下這種情況:申請的空間在函數結束時忘記釋放,造成記憶體洩漏。使用智能指針可以很大程度上的避免這個問題,因為智能指針就是一個類,當超出了類的作用域是,類會自動調用析構函數,析構函數會自動釋放資源。是以智能指針的作用原理就是在函數結束時自動釋放記憶體空間,不需要手動釋放記憶體空間。

  1. auto_ptr(c++98的方案,cpp11已經抛棄)

采用所有權模式。

auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”));

auto_ptr p2;

p2 = p1; //auto_ptr不會報錯.

此時不會報錯,p2剝奪了p1的所有權,但是當程式運作時通路p1将會報錯。是以auto_ptr的缺點是:存在潛在的記憶體崩潰問題!

  1. unique_ptr(替換auto_ptr)

unique_ptr實作獨占式擁有或嚴格擁有概念,保證同一時間内隻有一個智能指針可以指向該對象。它對于避免資源洩露(例如“以new建立對象後因為發生異常而忘記調用delete”)特别有用。

采用所有權模式,還是上面那個例子

複制代碼

1

2

3

unique_ptr p3 (new string (“auto”)); //#4

unique_ptr p4; //#5

p4 = p3;//此時會報錯!!

編譯器認為p4=p3非法,避免了p3不再指向有效資料的問題。是以,unique_ptr比auto_ptr更安全。

另外unique_ptr還有更聰明的地方:當程式試圖将一個 unique_ptr 指派給另一個時,如果源 unique_ptr 是個臨時右值,編譯器允許這麼做;如果源 unique_ptr 将存在一段時間,編譯器将禁止這麼做,比如:

unique_ptr pu1(new string (“hello world”));

unique_ptr pu2;

pu2 = pu1; // #1 not allowed

unique_ptr pu3;

pu3 = unique_ptr(new string (“You”)); // #2 allowed

其中#1留下懸挂的unique_ptr(pu1),這可能導緻危害。而#2不會留下懸挂的unique_ptr,因為它調用 unique_ptr 的構造函數,該構造函數建立的臨時對象在其所有權讓給 pu3 後就會被銷毀。這種随情況而已的行為表明,unique_ptr 優于允許兩種指派的auto_ptr 。

注:如果确實想執行類似與#1的操作,要安全的重用這種指針,可給它賦新值。C++有一個标準庫函數std::move(),讓你能夠将一個unique_ptr賦給另一個。例如:

unique_ptr ps1, ps2;

ps1 = demo(“hello”);

ps2 = move(ps1);

ps1 = demo(“alexia”);

cout << *ps2 << *ps1 << endl;

  1. shared_ptr

shared_ptr實作共享式擁有概念。多個智能指針可以指向相同對象,該對象和其相關資源會在“最後一個引用被銷毀”時候釋放。從名字share就可以看出了資源可以被多個指針共享,它使用計數機制來表明資源被幾個指針共享。可以通過成員函數use_count()來檢視資源的所有者個數。除了可以通過new來構造,還可以通過傳入auto_ptr, unique_ptr,weak_ptr來構造。當我們調用release()時,目前指針會釋放資源所有權,計數減一。當計數等于0時,資源會被釋放。

shared_ptr 是為了解決 auto_ptr 在對象所有權上的局限性(auto_ptr 是獨占的), 在使用引用計數的機制上提供了可以共享所有權的智能指針。

成員函數:

use_count 傳回引用計數的個數

unique 傳回是否是獨占所有權( use_count 為 1)

swap 交換兩個 shared_ptr 對象(即交換所擁有的對象)

reset 放棄内部對象的所有權或擁有對象的變更, 會引起原有對象的引用計數的減少

get 傳回内部對象(指針), 由于已經重載了()方法, 是以和直接使用對象是一樣的.如 shared_ptr sp(new int(1)); sp 與 sp.get()是等價的

  1. weak_ptr

weak_ptr 是一種不控制對象生命周期的智能指針, 它指向一個 shared_ptr 管理的對象. 進行該對象的記憶體管理的是那個強引用的 shared_ptr. weak_ptr隻是提供了對管理對象的一個通路手段。weak_ptr 設計的目的是為配合 shared_ptr 而引入的一種智能指針來協助 shared_ptr 工作, 它隻可以從一個 shared_ptr 或另一個 weak_ptr 對象構造, 它的構造和析構不會引起引用記數的增加或減少。weak_ptr是用來解決shared_ptr互相引用時的死鎖問題,如果說兩個shared_ptr互相引用,那麼這兩個指針的引用計數永遠不可能下降為0,資源永遠不會釋放。它是對對象的一種弱引用,不會增加對象的引用計數,和shared_ptr之間可以互相轉化,shared_ptr可以直接指派給它,它可以通過調用lock函數來獲得shared_ptr。

class B;

class A

{

public:

shared_ptr

pb_;

~A()

{

cout<<“A delete\n”;

}

};

class B

{

public:

shared_ptr pa_;

~B()

{

cout<<“B delete\n”;

}

};

void fun()

{

shared_ptr

pb(new B());

shared_ptr

pa(new A());

pb->pa_ = pa;

pa->pb_ = pb;

cout<<pb.use_count()<<endl;

cout<<pa.use_count()<<endl;

}

int main()

{

fun();

return 0;

}

可以看到fun函數中pa ,pb之間互相引用,兩個資源的引用計數為2,當要跳出函數時,智能指針pa,pb析構時兩個資源引用計數會減一,但是兩者引用計數還是為1,導緻跳出函數時資源沒有被釋放(A B的析構函數沒有被調用),如果把其中一個改為weak_ptr就可以了,我們把類A裡面的shared_ptr pb_; 改為weak_ptr pb_; 運作結果如下,這樣的話,資源B的引用開始就隻有1,當pb析構時,B的計數變為0,B得到釋放,B釋放的同時也會使A的計數減一,同時pa析構時使A的計數減一,那麼A的計數為0,A得到釋放。

注意的是我們不能通過weak_ptr直接通路對象的方法,比如B對象中有一個方法print(),我們不能這樣通路,pa->pb_->print(); 英文pb_是一個weak_ptr,應該先把它轉化為shared_ptr,如:shared_ptr p = pa->pb_.lock(); p->print();

https://www.nowcoder.com/tutorial/93/a34ed23d58b84da3a707c70371f59c21

智能指針的舉例子

28 虛函數和純虛函數

https://www.cnblogs.com/inception6-lxc/p/8597326.html

https://blog.csdn.net/zxxkkkk/article/details/109363441

29 哈希表,哈希沖突 解決辦法。

https://blog.csdn.net/u011109881/article/details/80379505

https://blog.csdn.net/z_ryan/article/details/78760944?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

30 線程的生命周期(開始 就緒 結束。。。。。)

31 構造函數和析構函數的子類基類調用順序

c++ 背景伺服器開發面試題目總結

32 Mysql的底層引擎是什麼了解嗎 innodb索引的b+樹

MySQL中四種常用存儲引擎的介紹

1>.InnoDB支援事物,而MyISAM不支援事物

2>.InnoDB支援行級鎖,而MyISAM支援表級鎖

3>.InnoDB支援MVCC, 而MyISAM不支援

4>.InnoDB支援外鍵,而MyISAM不支援

5>.InnoDB不支援全文索引,而MyISAM支援。(X)

33 程序間的通信方式

程序通信:

每個程序各自有不同的使用者位址空間,任何一個程序的全局變量在另一個程序中都看不到,是以程序之間要交換資料必須通過核心,在核心中開辟一塊緩沖區,程序A把資料從使用者空間拷到核心緩沖區,程序B再從核心緩沖區把資料讀走,核心提供的這種機制稱為程序間通信。

IPC的方式通常有管道(包括無名管道和命名管道)、消息隊列、信号量、共享存儲、Socket、Streams等。其中 Socket和Streams支援不同主機上的兩個程序IPC。

程序間的八種通訊方式

1.管道:速度慢,容量有限,隻有父子程序能通訊。

2.消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完資料的問題。

3.信号量:不能傳遞複雜消息,隻能用來同步

4.共享記憶體區:能夠很容易控制容量,速度快,但要保持同步,比如一個程序在寫的時候,另一個程序要注意讀寫的問題,相當于線程中的線程安全,當然,共享記憶體區同樣可以用作線程間通訊,不過沒這個必要,線程間本來就已經共享了同一程序内的一塊記憶體。

5.套接字: 可用于不同機器間的程序通信。

那種最快:

幾種方式的比較:

管道:速度慢,容量有限

消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完資料的問題。

信号量:不能傳遞複雜消息,隻能用來同步

共享記憶體區:能夠很容易控制容量,速度快,但要保持同步,比如一個程序在寫的時候,另一個程序要注意讀寫的問題,相當于線程中的線程安全,當然,共享記憶體區同樣可以用作線程間通訊,不過沒這個必要,線程間本來就已經共享了一塊記憶體的。

34 線程的同步方式

  • 臨界區(Critical Section)、互斥對象(Mutex):主要用于互斥控制;都具有擁有權的控制方法,隻有擁有該對象的線程才能執行任務,是以擁有,執行完任務後一定要釋放該對象。
  • 信号量(Semaphore)、事件對象(Event):事件對象是以通知的方式進行控制,主要用于同步控制

    https://blog.csdn.net/s_lisheng/article/details/74278765

    https://www.notown.club/?p=463

34.1 線程同步鎖的種類

https://blog.csdn.net/guoxiang3538/article/details/79376191

34.2 線程建立的基本方式

  • C++ 11新特性中,已經可以使用std::thread來建立線程了,
  • Windows系統為我們提供了相關API,我們可以使用他們來進行多線程程式設計。

    https://www.cnblogs.com/codingmengmeng/p/5913068.html

34.3 線程安全問題

35 程序和線程的差別,多程序和多線程程式設計概念

35.1 什麼是線程安全的

如果多線程的程式運作結果是可預期的,而且與單線程的程式運作結果一樣,那麼說明是“線程安全”的。

36 使用者态和核心态

雖然使用者态下和核心态下工作的程式有很多差别,但最重要的差别就在于特權級的不同,即權力的不同。運作在使用者态下的程式不能直接通路作業系統核心資料結構和程式,

當我們在系統中執行一個程式時,大部分時間是運作在使用者态下的,在其需要作業系統幫助完成某些它沒有權力和能力完成的工作時就會切換到核心态,

37 大資料之中資料的數目是n 選擇第k大的資料 (堆排序),時間複雜度是啥?(n-k)O(logk)?

選擇第k大的資料

38 int (*s[10])(int) s是一個什麼資料類型

39 寫一個函數指針 類似(void)func(這裡應該怎麼寫的)

提示:函數的值是int 并且函數的傳回值也是int

40 SQL語句之中的 delete和 drop的不同

41 作業系統中的虛拟記憶體 :硬碟一部分

https://www.cnblogs.com/Benjious/p/11611431.html

42 作業系統條件變量

42.1 作業系統:寫一個生産者,消費者的循環隊列 P V原語句

https://www.cnblogs.com/lustar/p/7689059.html

43 TCP擁塞控制怎麼進行

44 linux的記憶體管理(段頁方式)

45 關系型資料庫和非關系型資料庫額差別

https://blog.csdn.net/oChangWen/article/details/5342330

46 c++幾組比較

46.1 c++之中define vs const

C語言之const與define差別

修飾變量,使其不能被修改

  • 修飾函數參數,表明輸入的參數在參數内不能被修改

修飾指針

  • 常量指針,指向的内容不能被修改,即指向“常量”的指針 , const int *p
  • 指針常量,指針的指向不能改變,即指針類型的常量,int * const p
  • 修飾類的成員函數,表明其是常函數,即不能修改類的成員變量,const成員函數斌調用非const成員函數,因為非const成員函數可能會修改成員變量

46.2 private 和 protect:

46.3 struct vs union

46.4 友元函數,運算符重載

47 vector的擴容機制 以及 vector中push_back操作時間複雜度分析

http://blog.sina.com.cn/s/blog_a2a6dd380102w73e.html

48 B樹(B-)、B+樹,B*樹的簡單介紹

B樹、B-樹、B+樹、B*樹之間的關系

B樹和B+樹差別:

關鍵字數量不同:B+樹分支結點M個關鍵字,葉子節點也有M個;B樹分支結點則存在 k-1 個關鍵碼

資料存儲位置不同:B+樹資料存儲在葉子結點上;B樹存儲在每個結點上;

查詢不同:B+樹是從根節點到葉子節點的路徑;B樹是隻需要找到資料就可以

分支節點存儲資訊不同:B+樹存索引資訊;B樹存的是資料關鍵字

49 memcpy和strcpy的差別

strcpy針對字元串

memcpy可以是數組、對象、字元串等,需要指定長度

50 經典面試題之new和malloc的差別

重點在構造函數不同

  1. 屬性:

    new/delete是C++關鍵字,需要編譯器支援。malloc/free是庫函數,需要頭檔案支援。

  2. 參數:

    使用new操作符申請記憶體配置設定時無須指定記憶體塊的大小,編譯器會根據類型資訊自行計算。而malloc則需要顯式地指出所需記憶體的尺寸。

  3. 傳回類型

    new操作符記憶體配置設定成功時,傳回的是對象類型的指針,類型嚴格與對象比對,無須進行類型轉換,故new是符合類型安全性的操作符。而malloc記憶體配置設定成功則是傳回void * ,需要通過強制類型轉換将void*指針轉換成我們需要的類型。

  4. 配置設定失敗

    new記憶體配置設定失敗時,會抛出bac_alloc異常。malloc配置設定記憶體失敗時傳回NULL。

  5. 自定義類型
  • new會先調用operator new函數,申請足夠的記憶體(通常底層使用malloc實作)。然後調用類型的構造函數,初始化成員變量,最後傳回自定義類型指針。delete先調用析構函數,然後調用operator delete函數釋放記憶體(通常底層使用free實作)。
  • malloc/free是庫函數,隻能動态的申請和釋放記憶體,無法強制要求其做自定義類型對象構造和析構工作。
  1. 重載

    C++允許重載new/delete操作符,特别的,布局new的就不需要為對象配置設定記憶體,而是指定了一個位址作為記憶體起始區域,new在這段記憶體上為對象調用構造函數完成初始化工作,并傳回此位址。而malloc不允許重載。

  2. 記憶體區域

    new操作符從自由存儲區(free store)上為對象動态配置設定記憶體空間,而malloc函數從堆上動态配置設定記憶體。自由存儲區是C++基于new操作符的一個抽象概念,凡是通過new操作符進行記憶體申請,該記憶體即為自由存儲區。而堆是作業系統中的術語,是作業系統所維護的一塊特殊記憶體,用于程式的記憶體動态配置設定,C語言使用malloc從堆上配置設定記憶體,使用free釋放已配置設定的對應記憶體。自由存儲區不等于堆,如上所述,布局new就可以不位于堆中。

    https://blog.csdn.net/nie19940803/article/details/76358673

51 面向對象的特征并簡述

包括四大基本特征和五大基本原則。

特征:抽象、繼承、多态、封裝

原則:單一職責原則、開放封閉原則、替換原則、依賴原則、接口分離原則

面向對象的特征并簡述

52 如何避免死鎖

産生死鎖的四個必要條件:

(1) 互斥條件:一個資源每次隻能被一個程序使用。

(2) 請求和保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。

(3) 不可搶占條件:程序已獲得的資源,在末使用完之前,不能強行剝奪,隻能在程序使用完時由自己釋放。

(4) 循環等待條件:若幹程序之間形成一種頭尾相接的循環等待資源關系。

https://blog.csdn.net/weixin_41969690/article/details/107617634

53 c++類的加載過程

https://my.oschina.net/alphajay/blog/5029

  • 配置設定空間(Allocation)
  • 初始化(Initialization) ( 對象的初始化是通過初始化清單來完成,而對象的指派則才是通過構造函數,或者更準确的說應該是構造函數的實作體。)

54 MySQL 添加列,修改列,删除列

ALTER TABLE:添加,修改,删除表的列,限制等表的定義。

檢視列:desc 表名;

修改表名:alter table t_book rename to bbb;

添加列:alter table 表名 add column 列名 varchar(30);

删除列:alter table 表名 drop column 列名;

修改列名MySQL: alter table bbb change nnnnn hh int;

修改列名SQLServer:exec sp_rename’t_student.name’,‘nn’,‘column’;

修改列名Oracle:lter table bbb rename column nnnnn to hh int;

修改列屬性:alter table t_book modify name varchar(22);

55 C語言和c++的差別

C與C++的最大差別:在于它們的用于解決問題的思想方法不一樣。之是以說C++比C更先進,是因為“ 設計這個概念已經被融入到C++之中

  • 設計思想上:

    C++是面向對象的語言,而C是面向過程的結構化程式設計語言

面向過程的語言:
優點:性能比面向對象高,因為類調用時需要執行個體化,開銷比較大,比較消耗資源;比如單片機、嵌入式開發、 Linux/Unix等一般采用面向過程開發,性能是最重要的因素。 
缺點:沒有面向對象易維護、易複用、易擴充
面向對象的語言:
優點:易維護、易複用、易擴充,由于面向對象有封裝、繼承、多态性的特性,可以設計出低耦合的系統,使系統 更加靈活、更加易于維護 
缺點:性能比面向過程低
           
  • 文法上:

    C++具有封裝、繼承和多态三種特性

    C++相比C,增加多許多類型安全的功能,比如強制類型轉換、

    C++支援範式程式設計,比如模闆類、函數模闆等

C語言和c++的差別

C語言中struct和union的差別是什麼?

C和C++中struct的差別是什麼?

C語言中的struct與C++中的struct的差別表現在以下3個方面:

(1) C語言的struct不能有函數成員,而C++的struct可以有。

(2) C語言的struct中資料成員沒有private、public和protected通路權限的設定,而C++ 的struct的成員有通路權限設定。

(3) C語言的struct是沒有繼承關系的,而C++的struct卻有豐富的繼承關系。

C語言中的struct是使用者自定義資料類型,它是沒有權限設定的,它隻能是一些變量的集合體,雖然可以封裝資料卻不可以隐藏資料,而且成員不可以是函數。為 了和C語言相容,C++中就引入了 struct關鍵字。C++語言中的struct是抽象資料類型 (ADT),它支援成員函數的定義,同時它增加了通路權限,它的成員函數預設通路權限為 public。

C++中的 struct與class的差別是什麼?

具體而言,在C++中,class和struct做類型定義時隻有兩點差別:

(1) 預設繼承權限不同。class繼承預設是private繼承,而struct繼承預設是public繼承;

(2) class還用于定義模闆參數,就像typename,但關鍵字struct不用于定義模闆參數。

56 C++中基類的析構函數不是虛函數,會帶來什麼問題

C++中基類的析構函數不是虛函數,會帶來什麼問題

57 頭檔案中的ifndef/define/endif有什麼作用

https://blog.csdn.net/wangdd_199326/article/details/81324804

58 面試題:char * strcpy(char * strDest,const char * strSrc);

面試題:char * strcpy(char * strDest,const char * strSrc);

59 循環隊列的存儲空間為 Q(1:50) ,初始狀态為 front=rear=50 。經過一系列正常的入隊與退隊操作後, front=rear=25 ,此後又插入一個元素,則循環隊列中的元素個數為( )

https://www.nowcoder.com/questionTerminal/8da86fee838348af931e2b86a2c160bc

60 樂觀鎖與悲觀鎖的差別

61 static

修飾全局變量

修飾全局變量,不初始化預設初始為0,存儲在靜态存儲區,從聲明到程式結束一直存在

修飾局部變量

也存儲在靜态存儲區,作用域是局部作用域,當定義他的函數或者語句塊結束時,作用域結束,但該變量并沒有被銷毀,隻不過我們不能通路,直到該函數再次被調用

修飾類的資料成員

不屬于類的對象,類内聲明,類外初始化,類的靜态成員變量被所有對象共享,保證了共享性,又具備安全性

修飾類的成員函數

靜态成員函數隻能通路靜态成員變量,不能通路非靜态成員函數,原因是靜态成員函數不與任何對象綁定,是以不包含this指針,在靜态成員函數内部不能直接使用this指針,是以不能通路類的非靜态成員變量

修飾函數

即靜态函數,僅在聲明它的cpp檔案中使用,其他檔案不可使用

面試例子

static關鍵字的作用,修飾函數有什麼用?

加粗樣式static修飾的函數叫靜态函數,包括兩種

靜态函數出現在類裡,則它是一個靜态成員函數。靜态成員函數不與任何對象綁定,是以不包含this指針,在靜态成員函數内部不能直接使用this指針,即不能直接通路普通成員函數;靜态成員函數屬于類本身,在類加載時就會配置設定記憶體,可以通過類名直接去通路;雖然靜态成員函數不屬于類對象,但是可以通過類對象通路靜态成員函數。

普通的全局的靜态函數。限定在本源碼檔案中,不能在其他檔案調用(普通函數的定義和聲明預設情況下都是extern的,即可被其他檔案調用)。故好處在于:1)其他檔案中可以定義相同名字的函數。

62 map的插入的傳回值是啥

64 io複用問題

IO多路複用(IO Multiplexing)

65 動态連結和靜态連結

66 map低層紅黑樹的實作

67自定義 結構體作為 map的key 需要注意什麼呢

68 SQL語句之中的内連接配接,外連接配接

left join (左連接配接):傳回包括左表中的所有記錄和右表中連接配接字段相等的記錄。

  right join (右連接配接):傳回包括右表中的所有記錄和左表中連接配接字段相等的記錄。

  inner join (等值連接配接或者叫内連接配接):隻傳回兩個表中連接配接字段相等的行。

  full join (全外連接配接):傳回左右表中所有的記錄和左右表中連接配接字段相等的記錄。

左連接配接 ,右連接配接,内連接配接和全外連接配接的4者差別

69 線程池的介紹

C++11并發學習之六:線程池的實作

線程池的原理及C++線程池的封裝實作