C++工程師校招面試題庫導讀
一、學習說明
面試題庫中不包括面試中問到的專案,hr 面以及個人技術發展類,
? 專案是比較個性化的,沒辦法作為一個題庫來給大家參考,但是如果你有一個非常有含 金量 的專案的話,是非常加分的,而且你的專案可能也會被問的多一些;
? hr 面的話
一般來說技術面通過的話個人沒有太大的和公司不符合的問題都能通過;
? 技術發展類的話這個就完全看自己啦,主要考察的會是你對技術的熱愛和學習能力,比 如會 問一些你是如何學習 xxx技術的,或者能表達出你對技術的熱愛的地方等等,此處不做贅 述,
那么拋開這些,c++工程師中技術面中考察的占比如下:

需要注意的是:此圖不絕對,因為實際面試中面試官會根據你的簡歷去問,比如你的專案多可 能就問的專案多一些,或者你說哪里精通可能面試官就多去問你這些,而且此圖是根據題 庫資料整理 出來,并不是根據實際單場面試整理,比如基礎部分不會考那么多,會從中抽著考 ,
二、面試技巧
面試一般分為技術面和 hr 面,形式的話很少有群面,少部分企業可能會有一個交叉面,不 過總的來說,技術面基本就是考察你的專業技術水平的,hr 面的話主要是看這個人的綜合 素質以及家庭情況符不符合公司要求,一般來講,技術的話只要通過了技術面 hr 面基本上 是沒有問題(也有少數企業hr 面會刷很多人) 那我們主要來說技術面,技術面的話主要是考察專業技術知識和水平,我們是可以有一定的 技巧 的,但是一定是基于有一定的能力水平的, 所以也慎重的告訴大家,技巧不是投機取巧,是起到輔助效果的,技術面最主要的還是要有 實力,這里是基于實力水平之上的技巧,
這里告訴大家面試中的幾個技巧:
1、簡歷上做一個引導:
在詞匯上做好區分,比如熟悉 Java,了解 python,精通 c 語言
這樣的話對自己的掌握程度有個區分,也好讓面試官有個著重去問,python 本來寫的也只 是了解,自然就不會多問你深入的一些東西了,
2、在面試程序中做一個引導:
面試程序中盡量引導到自己熟知的一個領域,比如問到你說一下 DNS 尋址,然后你簡單回答(甚至這步也可以省略)之后,可以說一句,自己對這塊可能不是特別熟悉,對計算機網路中的運輸層比較熟悉,如果有具體的,甚至可以再加一句,比如TCP 和UDP 這樣的話你可以把整個面試程序往你熟知的地方引導,也能更傾向于體現出你的優勢而不是 劣勢,但是此方法僅限于掌握合適的度,比如有的知識點是必會的而你想往別處引就有點說 不過去了,比如讓你說幾個c++的關鍵字,你一個也說不上來,那可能就真的沒轍了,
3、在自我介紹中做一個引導:
一般面試的開頭都會有一個自我介紹,在這個位置你也可以盡情的為自己的優勢方面去引導,
4、面試程序中展示出自信:
面試程序中的態度也要掌握好,不要自卑,也不要傲嬌,自信的回答出每個問題,尤其遇到不會的問題,要么做一些引導,實在不能引導也可以先打打擦邊球,和面試官交流一下問題,看起來像是沒聽懂題意,這個程序也可以再自己思考一下,如果覺得這個程序可以免了的話也直接表明一下這個地方不太熟悉或者還沒有掌握好,千萬不要強行回答,
面試前的準備:
最重要的肯定是系統的學習了,有一個知識的框架,基礎知識的牢靠程度等,其中演算法尤其重要,越來越多公司還會讓你現場或者視頻面試中手寫代碼;
另一大重要的和加分項就是專案,在面試前,一定要練習回答自己專案的三個問題:
? 這是一個怎樣的專案
? 用到了什么技術,為什么用這項技術(以及每項技術很細的點以及擴展)
? 程序中遇到了什么問題,怎么解決的,
面試后需要做的:
面試完了的話就不用太在意結果了,有限的時間就應該做事半功倍的事情,當然,要保持電話郵箱暢通,不然別給你發 offer 你都不知道,
拋開這些,我們需要做的是及時將面試中的問題記錄下來,尤其是自己回答的不夠好的問題,一定要花時間去研究,并解決這些問題,下次面試再遇到相同的問題就能很好的解決,當然,即使 不遇到,你這個習慣堅持住,后面也可以作為一個經歷去跟面試官說,能表現出你對技術的喜愛和 鉆研的一個態度,同時,每次面試后你會發現自己的不足,查缺補漏的好機會,及時調整,在不斷的調整和查缺補漏的程序中,你會越來越好,
三、面試考點導圖

四、面試技術交流戳這里
如果你對校招求職或者職業發展很困惑,可以進群討論,相互學習,也有作業多年的攻城獅們,
面試考點正篇
一、基礎知識
1、基本語言
1、說一下 static 關鍵字的作用
考察點:C/C++
參考回答:
1.全域靜態變數
在全域變數前加上關鍵字 static,全域變數就定義成一個全域靜態變數. 靜態存盤區,在整個程式運行期間一直存在,
初始化:未經初始化的全域靜態變數會被自動初始化為0(自動物件的值是任意的,除非他被顯式初始化);
作用域:全域靜態變數在宣告他的檔案之外是不可見的,準確地說是從定義之處開始,到檔案結尾,
2.區域靜態變數
在區域變數之前加上關鍵字 static,區域變數就成為一個區域靜態變數,記憶體中的位置:靜態存盤區
初始化:未經初始化的全域靜態變數會被自動初始化為0(自動物件的值是任意的,除非他 被顯式初始化);
作用域:作用域仍為區域作用域,當定義它的函式或者陳述句塊結束的時候,作用域結束,但是 當區域靜態變數離開作用域后,并沒有銷毀,而是仍然駐留在記憶體當中,只不過我們不能再對 它進行訪問,直到該函式再次被呼叫,并且值不變;
3.靜態函式
在函式回傳型別前加 static,函式就定義為靜態函式,函式的定義和宣告在默認情況下都是 extern 的,但靜態函式只是在宣告他的檔案當中可見,不能被其他檔案所用,
函式的實作使用 static 修飾,那么這個函式只可在本cpp內使用,不會同其他cpp中的同名函式引起沖突;
warning:不要再頭檔案中宣告 static 的全域函式,不要在cpp 內宣告非static 的全域函式,如果 你要在多個 cpp 中復用該函式,就把它的宣告提到頭檔案里去,否則 cpp 內部宣告需加上static 修飾;
4.類的靜態成員
在類中,靜態成員可以實作多個物件之間的資料共享,并且使用靜態資料成員還不會破壞隱藏 的原則,即保證了安全性,因此,靜態成員是類的所有物件中共享的成員,而不是某個物件的 成員,對多 個物件來說,靜態資料成員只存盤
一處,供所有物件共用
- 類的靜態函式
靜態成員函式和靜態資料成員一樣,它們都屬于類的靜態成員,它們都不是物件成員,因此, 對靜態成員的參考不需要用物件名,
在靜態成員函式的實作中不能直接參考類中說明的非靜態成員,可以參考類中說明的靜態成 員(這點非常重要),如果靜態成員函式中要參考非靜態成員時,可通過物件來參考,從中可看出,呼叫靜態成員函式使用如下格式:<類名>::<靜態成員函式名>(<引數表>)
2、說一下 C++和 C 的區別
考察點:C 基礎
參考回答:
設計思想上:
C++是面向物件的語言,而 C 是面向程序的結構化編程語言
語法上:
C++具有多載、繼承和多型三種特性
C++相比 C,增加多許多型別安全的功能,比如強制型別轉換、
3、說一下 C++中 static 關鍵字的作用
考點:static 關鍵字
參考回答:
對于函式定義和代碼塊之外的變數宣告,static 修改識別符號的鏈接屬性,由默認 的external變為internal,作用域和存盤型別不改變,這些符號只能在宣告它們的源檔案中訪問,
對于代碼塊內部的變數宣告,static 修改識別符號的存盤型別,由自動變數改為靜態變數, 作用域和鏈接屬性不變,這種變數在程式執行之前就創建,在程式執行的整個周期都存在,
對于被 static 修飾的普通函式,其只能在定義它的源檔案中使用,不能在其他源檔案中被參考
對于被 static 修飾的類成員變數和成員函式,它們是屬于類的,而不是某個物件,所有物件共享一個靜態成員,靜態成員通過<類名>::<靜態成員>來使用,
4、請說一下 static 的作用
考察點:C/C++
參考回答:
- 全域靜態變數
在全域變數前加上關鍵字 static,全域變數就定義成一個全域靜態變數,
靜態存盤區,在整個程式運行期間一直存在,
初始化:未經初始化的全域靜態變數會被自動初始化為0(自動物件的值是任意的,除非他 被顯式初始化),
作用域:全域靜態變數在宣告他的檔案之外是不可見的,準確地說是從定義之處開始,到檔案結尾,
2.區域靜態變數
在區域變數之前加上關鍵字 static,區域變數就成為一個區域靜態變數,
記憶體中的位置:靜態存盤區,
初始化:未經初始化的全域靜態變數會被自動初始化為0(自動物件的值是任意的,除非他 被顯式初始化),
作用域:作用域仍為區域作用域,當定義它的函式或者陳述句塊結束的時候,作用域結束,但是當局 部靜態變數離開作用域后,并沒有銷毀,而是仍然駐留在記憶體當中,只不過我們不能再對 它進行訪問,直到該函式再次被呼叫,并且值不變,
- 靜態函式
在函式回傳型別前加 static,函式就定義為靜態函式,函式的定義和宣告在默認情況下都是 extern 的,但靜態函式只是在宣告他的檔案當中可見,不能被其他檔案所用,
函式的實作使用 static 修飾,那么這個函式只可在本cpp內使用,不會同其他cpp中的同名函式引起沖突,
warning:不要再頭檔案中宣告 static 的全域函式,不要在cpp 內宣告非static 的全域函式,如果你要在多個 cpp 中復用該函式,就把它的宣告提到頭檔案里去,否則 cpp 內部宣告需加上static修飾,
-
類的靜態成員
在類中,靜態成員可以實作多個物件之間的資料共享,并且使用靜態資料成員還不會破壞隱 藏的原則,即保證了安全性,因此,靜態成員是類的所有物件中共享的成員,而不是某個物件的成員,對多個物件來說,靜態資料成員只存盤一
處,供所有物件共用, -
類的靜態函式
靜態成員函式和靜態資料成員一樣,它們都屬于類的靜態成員,它們都不是物件成員,因此,對靜態成員的參考不需要用物件名,
在靜態成員函式的實作中不能直接參考類中說明的非靜態成員,可以參考類中說明的靜態成 員(這點非常重要),如果靜態成員函式中要參考非靜態成員時,可通過物件來參考,從中可看出,呼叫靜態成員函式使用如下格式:<類名>::<靜態成員函式名>(<引數表>);
5、說一說 c++中四種 cast 轉換
考察點:C/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 的強制轉換表面上看起來功能強大什么都能轉,但是轉化不夠明確,不能進行錯誤檢查,容易出錯,
6、請說一下 C/C++ 中指標和參考的區別?
考察點:C/C++基礎知識
參考回答:
1.指標有自己的一塊空間,而參考只是一個別名;
2.使用 sizeof 看一個指標的大小是 4,而參考則是被參考物件的大小;
3.指標可以被初始化為 NULL,而參考必須被初始化且必須是一個已有物件 的參考;
4.作為引數傳遞時,指標需要被解參考才可以對物件進行操作,而直接對參考的修改都會改變參考所指向的物件;
5.可以有 const 指標,但是沒有 const 參考;
6.指標在使用中可以指向其它物件,但是參考只能是一個物件的參考,不能被改變;
7.指標可以有多級指標(**p),而參考至于一級;
8.指標和參考使用++運算子的意義不一樣;
7、給定三角形 ABC 和一點 P(x,y,z),判斷點 P 是否在 ABC 內,給出思路并手寫代碼
參考回答:
根據面積法,如果 P在三角形ABC內,那么三角形ABP的面積+三角形BCP 的面積+三角形ACP 的面積應該等于三角形ABC 的面積,演算法如下:
#include <iostream>
#include <math.h> using
namespace std;
#define ABS_FLOAT_0 0.0001
struct point_float
{
float x;
float y;
};
/**
*@brief 計算三角形面積
*/
float GetTriangleSquar(const point_float pt0, const point_float pt1, const point_float pt2)
{
point_float AB, BC;
AB.x = pt1.x - pt0.x;
AB.y = pt1.y - pt0.y;
BC.x = pt2.x - pt1.x;
BC.y = pt2.y - pt1.y;
return fabs((AB.x *BC.y - AB.y *BC.x)) / 2.0f;
}
/**
*@brief 判斷給定一點是否在三角形內或邊上
*/
bool IsInTriangle(const point_float A, const point_float B, const point_float C, const point_float D)
{
float SABC, SADB, SBDC, SADC;
SABC = GetTriangleSquar(A, B, C);
SADB = GetTriangleSquar(A, D, B); SBDC
= GetTriangleSquar(B, D, C); SADC =
GetTriangleSquar(A, D, C);
float SumSuqar = SADB + SBDC + SADC;
if ((-ABS_FLOAT_0 < (SABC - SumSuqar)) && ((SABC - SumSuqar) < ABS_FLOAT_0))
{
return true;
}
else
{
return false;
}
}
8、請你說一下你理解的 c++中的 smart pointer 四個智能指標:
shared_ptr,unique_ptr,weak_ptr,auto_ptr
考察點:C++智能指標
參考回答:
C++里面的四個智能指標: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三個是c++11支持,并且第一個已經被 11 棄用,
為什么要使用智能指標:
智能指標的作用是管理一個指標,因為存在以下這種情況:申請的空間在函式結束時忘記釋放 ,造成記憶體泄漏,使用智能指標可以很大程度上的避免這個問題,因為智能指標就是一個類,當超出了類的作用域是,類會自動呼叫解構式,解構式會自動釋放資源,所以智能指標的作用原理就是在函式結束時自動釋放記憶體空間,不需要手動釋放記憶體空間,
-
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 的缺點是:存在潛在的記憶體崩潰問題! -
unique_ptr(替換auto_ptr)
unique_ptr 實作獨占式擁有或嚴格擁有概念,保證同一時間內只有一個智能指標可以指向該物件,它對于避免資源泄露(例如“以new創建物件后因為發生例外而忘記呼叫delete”)特別有用,
采用所有權模式,還是上面那個例子
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;
- 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()是等價的
- 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<B> pb_;
~A()
{
cout<<"A delete\n";
}
};
class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout<<"B delete\n";
}
};
void fun()
{
shared_ptr<B> pb(new B());
shared_ptr<A> 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();
9、怎么判斷一個數是二的倍數,怎么求一個數中有幾個 1,說一下你的思路并手寫代碼
考察點:演算法
參考回答:
1、判斷一個數是不是二的倍數,即判斷該數二進制末位是不是 0:
a % 2 == 0 或者 a & 0x0001 == 0,
2、求一個數中 1 的位數,可以直接逐位除十取余判斷:
int fun(long x)
{
int _count = 0;
while(x)
{
if(x % 10 == 1)
++_count;
x /= 10;
}
return _count;
}
int main()
{
cout << fun(123321) << endl;
return 0;
}
10、請回答一下陣列和指標的區別
知識點:陣列 指標
參考回答:
指標和陣列的主要區別如下:

11、請你回答一下野指標是什么?
考點:指標
參考回答:
野指標就是指向一個已洗掉的物件或者未申請訪問受限記憶體區域的指標
12、請你介紹一下 C++中的智能指標
考點:shared_ptr
參考回答:
智能指標主要用于管理在堆上分配的記憶體,它將普通的指標封裝為一個堆疊物件,當堆疊物件的 生存 周期結束后,會在解構式中釋放掉申請的記憶體,從而防止記憶體泄漏,C++ 11 中最常用的智能指標型別為shared_ptr,它采用參考計數的方法,記錄當前記憶體資源被多少個智能指標參考,該參考計數的記憶體在堆上分配,當新增一個時參考計數加1,當過期時參考計數減一,只有參考計數為0 時,智能指標 才會自動釋放參考的記憶體資源,對shared_ptr 進行初始化時不能將
一個普通指標直接賦值給智能指標,因為一個是指標,一個是類,可以通過make_shared 函式或者通過建構式傳入普通指標,并可以通過 ,
關于面試,關于技術,需要溝通交流點這里,

面試,技術,崗位資訊全網覆寫中~
一切只為渴望更優秀的自己!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/252715.html
標籤:其他
下一篇:2021-01-25
