1. 程式人生 > >網易遊戲開發面試題分享

網易遊戲開發面試題分享

原貼地址:http://www.zhihu.com/question/30034222

·●    inline關鍵字是做什麼用的?inline關鍵字在什麼情況下會展開失敗?

程式碼長度過大,會導致展開失敗。inline類似於將程式碼直接替換,但是又不是。省去了呼叫函式的開銷。增快了程式碼的執行效率。

  • sizeof一個空類是多大?為什麼?編譯器為什麼這麼做?
  • 1個位元組,任何一個例項在記憶體中都有一個獨一無二的地址,為了達到這個目的,編譯器往往會給一個空類隱含的加一個位元組,這樣空類在例項化後在記憶體得到了獨一無二的地址
  • 在這個類中新增一個virtual函式後再sizeof,這時是多大?為什麼?
  • 4個位元組,有virtual函式,就會對應一個指向虛擬函式表的vptr指標,指標的大小在32位系統中是4個位元組.
  • 將這個類再virtual繼承一個其它的空類,這是多大?為什麼?
  • 12個位元組,這個類本身大小為4個位元組,空類的大小為1個位元組,加上虛基類偏移量表指標4個指標,又因為要指標對齊(4個位元組),故一起12個位元組
  • 類有哪幾種許可權,分別說明?
  • private,protected,public
  • class A :class B{},A是私有繼承還是? 私有繼承是做什麼用的?
  • 預設是私有繼承,私有繼承後,基類所有成員在派生類中為private成員。私有基類的public成員和protected成員在私有派生類中的訪問屬性相當於派生類中的私有成員,即派生類的成員函式能訪問它們,而在派生類外不能訪問它們。私有基類的私有成員在派生類中稱為不可訪問的成員,只有基類的成員函式可以引用它們。
  • struct S{
  • char a;
  •    int b;
  •    static long c;
  • }
  • 請問sizeof(S)是多少?為什麼,有什麼好處?
  • 32位系統上,是8個位元組,位元組對齊,方便定址操作。
  • 子類的虛擬函式中能不能呼叫父類的虛擬函式,為什麼?
  • 有純虛擬函式的類能不能例項化?
  • 不能,有純虛擬函式的類是抽象類,只能被繼承,不能例項化。包含純虛函是的類派生出來的類都必須重寫這個純虛擬函式,舉個例子,動物可以派生出狗,貓,牛等,動物本身是不可以被例項化的。
  • C++多型有哪幾種?
  • 靜態多型(函式過載和運算子過載),是在編譯的時候,就確定呼叫函式的型別;動態多型(虛擬函式實現),在執行的時候,才能確定呼叫的是哪個函式,動態繫結。執行基類指標指向派生類的物件,並呼叫派生類的函式。
  • 應用形式上:靜多型是發散式的,讓相同的實現程式碼應用於不同的場合。動多型是收斂式的,讓不同的實現程式碼應用於相同的場合。
  • 思維方式上:靜多型是泛型式程式設計風格,它看重的是演算法的普適性;動多型是物件式程式設計風格,它看重的是介面和實現的分離度。
  • C++是怎麼實現動態多型的?
  • 虛擬函式表和指向虛擬函式表的vptr指標。這個需要注意vptr指標的分佈初始化問題,是在建構函式之後,初始化列表和函式體之前完成的。
  • 物件中的VPTR指標什麼時候被初始化?

    Vptr指標初始化的過程: 
    1.物件在建立的時,由編譯器對VPTR指標進行初始化 
    2.只有當物件的構造完全結束後VPTR的指向才最終確定 
    3.父類物件的VPTR指向父類虛擬函式表 
    4.子類物件的VPTR指向子類虛擬函式表

    當定義一個子類物件的時候比較麻煩,因為構造子類物件的時候會首先呼叫父類的建構函式然後再呼叫子類的建構函式。當呼叫父類的建構函式的時候,此時會建立Vptr指標(也可以認為Vptr指標是屬於父類的成員,所以在子類中重寫虛擬函式的時候virtual關鍵字可以省略,因為編譯器會識別父類有虛擬函式,然後就會生成Vptr指標變數),該指標會指向父類的虛擬函式表;然後再呼叫子類的建構函式,此時Vptr又被賦值指向子類的虛擬函式表。 
    (執行父類的建構函式的時候Vptr指標指向的是父類的虛擬函式表,所以只能執行父類的虛擬函式) 
    上面的過程是Vptr指標初始化的過程。 
    這是因為這個原因,在建構函式中呼叫虛擬函式不能實現多型。

  • 簡要說說C++的靜態多型?
  • 函式過載和運算子過載,見上上題。
  • C++編譯後的函式符號和C語言編譯後的函式符號有哪些區別?為什麼
  • C++語言支援函式過載,C語言不支援函式過載。函式被C++編譯後在庫中的名字與C語言的不同。假設某個函式的原型為void func(int x,int y)。該函式被C編譯器編譯後在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。 C++中提供了C連線交換指定符號 extern "C" 解決名字匹配問題。
  • C++智慧指標有哪些?auto_ptr和share_ptr有什麼區別?他們有什麼作用?
  • STL一共給我們提供了四種智慧指標:auto_ptr,unique_ptr,shared_ptr和weak_ptr
  • auto_ptr的初衷是用來實現智慧指標的,實現記憶體的自動回收。那麼如何實現智慧的呢?智慧指標最基本的概念是引用計數,也就是智慧指標內部有一個計數器,記錄了當前記憶體資源到底有多少指標在引用(可以引用這個資源),當新增加一個可以訪問這個資源的引用時,計數器會加1,反之會減去1,當計數器為0時,智慧指標會自動釋放它所管理的資源。手動申請,自動釋放,就是智慧的體現。RF:http://www.zhihu.com/question/20368881
  • 有序vector和list二分查詢的時間複雜度分別是多少?
  • vector的二分相當於陣列的二分,時間複雜度是O(logn),list沒辦法二分,只能每次從頭到尾找,時間複雜度為O(n)。
  • vector自動擴容是按什麼大小進行的?
  • 預設的情況下vector的擴充套件機制是按2倍大小進行擴充套件的。在整個大小擴充套件的過程中,主要的步驟是:1.為需要的新容量分配足夠的記憶體;2.將元素從原來的記憶體拷貝到新記憶體中去;3.銷燬原來記憶體中的元素;4.歸還原來的記憶體。
  • 圖的搜尋有哪幾種方式?廣搜要怎麼做?需要什麼額外空間嗎
  • DFS和BFS,其中BFS需要開闢記憶體。
  • 給定一個迷宮,部分座標是無法通過的,求某兩點間最短路徑?
  • 廣搜+並查集
  • 簡述Dijkstra演算法的過程,描述一下A Star演算法
  • 找出一個無序陣列中大小後K個數據?
  • 類似於快速排序的思想,隨機選取一個元素,把所有小於等於這個元素的資料移到左邊,所有大於這個元素的資料移動到右邊。
  • 如果這個元素成了第K個數,直接返回這個數。如果左邊的個數大於K,不管右邊的數了,在左邊重複上面的過程。如果左邊的個數等於T<K,不管左邊的數了,重複上面的過程,只是K=K-T-1。平均情況下,第一次劃分的時間複雜度是O(N),第二次就是O(N/2),總共是O(n+n/2+n/4+...)=O(n)
  • Set的底層實現是什麼?紅黑樹是做什麼用的?額外開銷是多少?
  • set的底層實現是紅黑樹。紅黑樹是一種平衡二叉查詢樹。結點是紅色或黑色。根節點是黑色,每個葉子結點都是黑色,每個紅色結點的兩個孩子結點都是黑色。從每個葉子到根的所有路徑上不能有兩個連續的紅色結點。從任一結點到其每個葉子的所有路徑都包含相同數目的黑色結點。
  • 紅海色書和AVL樹一樣都對插入時間和刪除時間以及查詢時間提供了最好可能的最壞保障。時間複雜度是O(logn),需要額外的空間也是O(logn)
  • 程式有哪幾種連結方式?分別說明區別?哪種效率高?如果一個動態庫沒有.lib和標頭檔案,要怎麼使用裡面的函式?
  • 靜態連結、裝入時動態連結、執行時動態連結。
  • 1.靜態連結:在程式執行之前,先將各個目標模組及它們所需的庫函式,連結成一個完整的裝配模組,以後不再拆開。我們把這種事先進行連結的方式稱為靜態連結方式。
  • 2.裝入時動態連結:這是指將使用者源程式編譯後所得到的一組目標模組,在裝入記憶體時,採用邊裝入邊連結的連結方式。
  • 3.執行時動態連結:這是指對某些目標模組的連結,是在程式執行中需要該目標模組時,才對它進行的連結。
  • 第三種方式效率較高。還可以節省大量的記憶體空間。
  • 執行緒和程序的區別?
  • 執行緒使用共享資源會出現什麼問題?需要怎麼做?
  • 如何進行執行緒同步?在Windows下舉例?分使用者模式下同步和核心模式下同步 討論?
  • 使用者模式下的方法有:原子操作(例如一個單一的全域性變數),臨界區。

    核心模式下的方法有:事件,訊號量,互斥量。


  • 堆和棧的區別?
  • 執行緒死鎖的幾個條件是什麼?
  • (1)互斥條件:指執行緒對所分配的資源進行排他性使用,即在一段時間內某資源只由一個執行緒佔用。
  • (2)請求和保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。
  • (3)不可剝奪條件:程序已獲得的資源,在未使用之前,不能強行剝奪。
  • (4)環路等待條件:指在發生死鎖時,必然存在一個執行緒-資源的環形鏈,即執行緒集合{P0,P1,,P2,P3,...,Pn}中的P0正在等待P1佔用的資源;P1正在等待P2佔用的資源,...,Pn正在等待已被P0佔用的資源。
  • 給定兩個執行緒,A,B兩個鎖,舉個造成死鎖的例子?
  • 多個程序同時佔有對方需要的資源而同時請求對方的資源,而它們在得到請求之前不會釋放所佔有的資源
  • TCP和UDP的區別?分別舉例它們的上層協議?
  • TCP是基於連線的,可靠的,偏向於傳輸大量資料,速度慢,http,ftp,smtp,telnet使用了tcp;UDP是無連線的,不可靠的,偏向於傳輸少量資料,速度快,dns,tftp,rip,snmp,nfs等使用了udp。
  • 你用過哪些設計模式?
  • 工廠方法和抽象工廠有哪些區別?
  • 工廠方法模式屬於物件建立型模式,它定義一個使用者建立物件的介面,讓子類決定例項化哪一個類。工廠方法模式使一個類的例項化延遲到其子類。具體來說就是一個一個抽象產品類,派生出很多個具體產品類;同時,一個抽象工廠類,派生出多個具體工廠類。而每個具體工廠類只能建立一個具體產品類的例項。
  • 抽象工廠模式也屬於物件建立型模式,它提供了一個建立一系列相關或相互依賴物件的介面,而無須制定它們具體的類。具體來說就是在多個抽象產品類中,每個抽象產品類可以派生出多個具體產品類。一個抽象工廠類,可以派生出多個具體工廠類。每個具體工廠類可以建立多個具體產品類的例項。
  • 區別:工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。工廠方法模式的具體工廠類只能建立一個具體產品類的例項,而抽象工廠模式可以建立多個。
  • 工廠方法:說白了就是一個方法,這個方法是建立具體的產品的,它要求所有的工廠都具有同一個簽名的方法,必要時重寫該方法;
  • 抽象工廠:不能直接建立產品,只能建立工廠,即抽象工廠建立的產品是工廠。
  • 程序間通訊有哪幾種方式?在特定環境(比如兩個程式需要共享一個文字)下哪種效率最高?Windows下如何進行記憶體共享?
  • 無名管道,有名管道,訊號量,訊號,高階管道,訊息佇列,共享記憶體,sokect等,共享記憶體的效率最高,因為它可以直接讀寫記憶體,而不需要任何的資料拷貝。windows下主要通過對映機制實現的。共享記憶體的方式原理就是將一份實體記憶體對映到不同程序各自的虛擬地址空間中,這樣每個程序都可以讀取同一份資料,從而實現程序通訊。因為是通過記憶體操作實現通訊,因此是一種最搞笑的資料交換方法。
  • 給定1000億個資料,要找出其中最大的一個值,記憶體只有1G?
  • 大檔案變小檔案,然後每個檔案裡hash_map統計最大的值,然後再歸併排序。
  • 給定1000億個資料,裡邊有的資料有重複,要求設計一個演算法刪除重複資料?要求儘量快。
  • 先取模分成小檔案,然後每個檔案使用hash_map或者trie樹。