2025年CC++程序員常見筆試題含解析及答案_第1頁
2025年CC++程序員常見筆試題含解析及答案_第2頁
2025年CC++程序員常見筆試題含解析及答案_第3頁
2025年CC++程序員常見筆試題含解析及答案_第4頁
2025年CC++程序員常見筆試題含解析及答案_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

2025年CC++程序員常見筆試題含解析及答案1.智能指針自定義刪除器題目:設(shè)計(jì)一個(gè)使用`std::unique_ptr`管理文件描述符(int類型)的場(chǎng)景,要求當(dāng)`unique_ptr`析構(gòu)時(shí)自動(dòng)關(guān)閉文件描述符。需寫出關(guān)鍵代碼并說明自定義刪除器的實(shí)現(xiàn)邏輯。解析:`std::unique_ptr`默認(rèn)刪除器是調(diào)用`delete`釋放堆內(nèi)存,但管理非堆資源(如文件描述符)時(shí)需自定義刪除器。刪除器類型需作為`unique_ptr`的第二個(gè)模板參數(shù),且刪除器對(duì)象需能通過`operator()`接收被管理的指針(或直接是資源句柄)。答案:```cppinclude<memory>include<unistd.h>//close函數(shù)聲明//自定義刪除器類型,用于關(guān)閉文件描述符structFileDescriptorDeleter{voidoperator()(intfd)const{if(fd&&fd!=-1){close(fd);//關(guān)閉文件描述符fd=-1;//避免重復(fù)關(guān)閉}deletefd;//釋放存儲(chǔ)文件描述符的堆內(nèi)存(注意:這里管理的是堆上的int)}};//另一種更直接的方式(管理非堆資源時(shí),可直接持有句柄而非指針)usingUniqueFd=std::unique_ptr<int,decltype([](intfd){if(fd&&fd!=-1){close(fd);fd=-1;}deletefd;})>;//使用示例intmain(){intfd_ptr=newint(open("test.txt",O_RDONLY));//假設(shè)open成功返回非-1值std::unique_ptr<int,FileDescriptorDeleter>uptr(fd_ptr);//或使用lambda作為刪除器(C++14起支持泛型lambda)autodeleter=[](intfd){if(fd&&fd!=-1){close(fd);fd=-1;}deletefd;};std::unique_ptr<int,decltype(deleter)>uptr2(fd_ptr,deleter);return0;}```關(guān)鍵邏輯:刪除器需正確處理資源釋放(如調(diào)用`close`),并避免重復(fù)釋放。若直接管理句柄(而非堆指針),可使用`std::unique_ptr<int,void()(int)>`,但需注意`unique_ptr`默認(rèn)管理的是指針類型,因此需將句柄存儲(chǔ)在堆內(nèi)存中(或使用`std::experimental::observer_ptr`配合自定義刪除器,但非標(biāo)準(zhǔn))。2.虛函數(shù)與多繼承的內(nèi)存布局題目:已知類繼承關(guān)系如下,畫出`D`類對(duì)象的內(nèi)存布局(假設(shè)32位系統(tǒng),無虛函數(shù)覆蓋,無成員變量):```cppclassA{virtualvoida(){}};classB:virtualpublicA{virtualvoidb(){}};classC:virtualpublicA{virtualvoidc(){}};classD:publicB,publicC{virtualvoidd(){}};```解析:虛繼承用于解決菱形繼承的二義性問題,派生類會(huì)包含虛基類表(vbtable)指針,指向虛基類的偏移量。每個(gè)有虛函數(shù)的類有獨(dú)立的虛函數(shù)表(vtable)指針。32位系統(tǒng)中指針占4字節(jié)。答案:`D`對(duì)象的內(nèi)存布局(從低地址到高地址):-B的vtable指針(指向B的vtable,包含B::b()和D::d(),因D覆蓋了B的虛函數(shù)?不,題目中D的d()是新虛函數(shù),未覆蓋任何基類。實(shí)際B的vtable包含B::b()和A::a()(若未覆蓋),但題目假設(shè)無虛函數(shù)覆蓋,因此B的vtable包含B::b()和A的a()?需明確:每個(gè)類的vtable包含自身定義的虛函數(shù),未覆蓋的基類虛函數(shù)仍保留在基類vtable中。正確布局應(yīng)為:-B子對(duì)象:-B的vtable指針(指向B的vtable:包含B::b())-虛基類表指針(指向B的虛基類表,記錄到A的偏移量)-C子對(duì)象:-C的vtable指針(指向C的vtable:包含C::c())-虛基類表指針(指向C的虛基類表,記錄到A的偏移量)-D的vtable指針(若D新增虛函數(shù),需擴(kuò)展最近的基類vtable?實(shí)際D的虛函數(shù)會(huì)被添加到其第一個(gè)直接非虛基類(B)的vtable中,因此可能不單獨(dú)存在D的vtable指針)-共享的A子對(duì)象(因虛繼承):-A的vtable指針(指向A的vtable:包含A::a())注:實(shí)際布局因編譯器而異(如MSVC和GCC的虛表布局不同),但核心是虛繼承導(dǎo)致虛基類表指針的存在,且虛基類A在D中只存在一份。3.vector的迭代器失效問題題目:分析以下代碼的輸出結(jié)果,并說明迭代器失效的原因。```cppinclude<vector>include<iostream>usingnamespacestd;intmain(){vector<int>vec={1,2,3,4,5};autoit=vec.begin();vec.push_back(6);//操作1cout<<it<<endl;//輸出?vec.insert(it,0);//操作2cout<<vec.size()<<endl;//輸出?return0;}```解析:vector的`push_back`可能導(dǎo)致擴(kuò)容(當(dāng)當(dāng)前容量不足時(shí)),此時(shí)會(huì)重新分配內(nèi)存,原迭代器、指針、引用失效。`insert`操作若在非end位置插入元素,可能導(dǎo)致插入點(diǎn)之后的迭代器失效(若未擴(kuò)容),但插入點(diǎn)之前的迭代器是否失效取決于是否擴(kuò)容。答案:操作1中,`vec`原容量為5(假設(shè)初始容量為5),`push_back(6)`需要擴(kuò)容(容量變?yōu)?0,假設(shè)),因此原迭代器`it`失效。此時(shí)`it`為未定義行為(可能崩潰或輸出隨機(jī)值)。操作2中,`it`已失效,使用失效的迭代器調(diào)用`insert`會(huì)導(dǎo)致未定義行為(如程序崩潰)。因此實(shí)際運(yùn)行中,代碼可能在操作2處崩潰,無法輸出第二個(gè)結(jié)果。擴(kuò)展:vector的迭代器失效規(guī)則:-插入(`push_back`/`insert`等):若導(dǎo)致擴(kuò)容,所有迭代器失效;否則,插入點(diǎn)之后的迭代器失效,之前的有效。-刪除(`erase`/`pop_back`等):刪除點(diǎn)之后的迭代器失效,之前的有效(`pop_back`僅使end()失效)。4.手寫strncpy函數(shù)(考慮內(nèi)存重疊)題目:實(shí)現(xiàn)`charstrncpy(chardest,constcharsrc,size_tn)`,要求處理源串長(zhǎng)度小于n時(shí)填充'\0',且處理`dest`與`src`內(nèi)存重疊的情況。解析:標(biāo)準(zhǔn)`strncpy`不保證目標(biāo)串以'\0'結(jié)尾(除非源串長(zhǎng)度小于n),且不處理內(nèi)存重疊(可能導(dǎo)致覆蓋)。需先判斷是否重疊,若重疊則從后向前復(fù)制。答案:```cppcharstrncpy(chardest,constcharsrc,size_tn){if(dest==nullptr||src==nullptr||n==0)returndest;chardest_start=dest;size_tsrc_len=0;//計(jì)算源串長(zhǎng)度(不超過n)while(src_len<n&&src[src_len]!='\0')src_len++;//判斷是否內(nèi)存重疊:dest在[src,src+n)區(qū)間內(nèi)if(dest>src&&dest<src+n){//重疊,從后向前復(fù)制for(size_ti=src_len;i>0;--i){dest[i-1]=src[i-1];}//填充剩余的'\0'(若src_len<n)for(size_ti=src_len;i<n;++i){dest[i]='\0';}}else{//非重疊,從前向后復(fù)制for(size_ti=0;i<src_len;++i){dest[i]=src[i];}//填充剩余的'\0'for(size_ti=src_len;i<n;++i){dest[i]='\0';}}returndest_start;}```關(guān)鍵點(diǎn):-先計(jì)算源串實(shí)際長(zhǎng)度`src_len`(不超過n),避免越界。-內(nèi)存重疊判斷:若`dest`在`src`和`src+n`之間,說明復(fù)制會(huì)覆蓋未讀取的源數(shù)據(jù),需反向復(fù)制。-源串長(zhǎng)度小于n時(shí),目標(biāo)串后續(xù)字節(jié)填充'\0'(與標(biāo)準(zhǔn)`strncpy`一致)。5.多線程下的原子操作與內(nèi)存順序題目:分析以下代碼是否線程安全,若不安全請(qǐng)說明原因并給出修復(fù)方案。```cppinclude<atomic>include<thread>std::atomic<int>count(0);voidincrement(){for(inti=0;i<1000;++i){count.fetch_add(1,std::memory_order_relaxed);}}intmain(){std::threadt1(increment);std::threadt2(increment);t1.join();t2.join();//期望count為2000,實(shí)際是否可能小于2000?return0;}```解析:`fetch_add`是原子操作,保證計(jì)數(shù)的原子性,但`memory_order_relaxed`僅保證操作本身的原子性,不提供線程間的同步。但在此場(chǎng)景中,兩個(gè)線程僅修改同一個(gè)原子變量,最終結(jié)果應(yīng)為2000,因?yàn)閌fetch_add`的原子性保證了每次遞增的可見性。答案:代碼是線程安全的,最終`count`的值一定是2000。`std::memory_order_relaxed`在此處足夠,因?yàn)闆]有其他共享變量需要同步,僅需保證`fetch_add`的原子性即可。擴(kuò)展:若存在其他共享狀態(tài)(如標(biāo)志位),則需使用更嚴(yán)格的內(nèi)存順序(如`memory_order_acq_rel`)保證操作的順序性。例如,若一個(gè)線程寫入數(shù)據(jù)后設(shè)置標(biāo)志位,另一個(gè)線程讀取標(biāo)志位后讀取數(shù)據(jù),此時(shí)需`memory_order_release`(寫標(biāo)志位)和`memory_order_acquire`(讀標(biāo)志位)保證數(shù)據(jù)先于標(biāo)志位被寫入和讀取。6.模板元編程:編譯期計(jì)算斐波那契數(shù)題目:使用C++模板元編程實(shí)現(xiàn)編譯期計(jì)算斐波那契數(shù)列的第n項(xiàng)(n≥0),要求支持n=0時(shí)返回0,n=1時(shí)返回1。解析:模板元編程通過遞歸模板特化實(shí)現(xiàn)編譯期計(jì)算。斐波那契數(shù)列的遞推式為`fib(n)=fib(n-1)+fib(n-2)`,邊界條件為`fib(0)=0`,`fib(1)=1`。答案:```cpptemplate<size_tn>structFibonacci{staticconstexprsize_tvalue=Fibonacci<n-1>::value+Fibonacci<n-2>::value;};template<>structFibonacci<0>{staticconstexprsize_tvalue=0;};template<>structFibonacci<1>{staticconstexprsize_tvalue=1;};//使用示例constexprsize_tfib_5=Fibonacci<5>::value;//fib_5=5(0,1,1,2,3,5)```關(guān)鍵點(diǎn):-主模板處理n≥2的情況,遞歸調(diào)用`n-1`和`n-2`。-特化模板處理邊界條件n=0和n=1。-`constexpr`保證值在編譯期計(jì)算。擴(kuò)展:C++14起支持`constexpr`函數(shù),可更簡(jiǎn)潔地實(shí)現(xiàn)編譯期斐波那契計(jì)算:```cppconstexprsize_tfibonacci(size_tn){return(n==0)?0:(n==1)?1:fibonacci(n-1)+fibonacci(n-2);}constexprsize_tfib_5=fibonacci(5);//同樣得到5```7.內(nèi)存對(duì)齊與結(jié)構(gòu)體大小計(jì)算題目:計(jì)算以下結(jié)構(gòu)體在64位Linux(GCC)下的大?。僭O(shè)`int`占4字節(jié),`long`占8字節(jié),`char`占1字節(jié)):```cppstructExample{chara;intb;longc;chard;inte;longf;};```解析:GCC默認(rèn)對(duì)齊規(guī)則為結(jié)構(gòu)體成員的對(duì)齊數(shù)取自身大小與編譯器最大對(duì)齊數(shù)(64位為8字節(jié))的較小值。結(jié)構(gòu)體整體大小需是最大成員對(duì)齊數(shù)的整數(shù)倍。各成員偏移量計(jì)算:-`a`(char,1字節(jié)):偏移0,對(duì)齊1,滿足。-`b`(int,4字節(jié)):需偏移量是4的倍數(shù),因此填充3字節(jié)(偏移0+1=1,下一個(gè)可用偏移4),`b`在偏移4。-`c`(long,8字節(jié)):需偏移量是8的倍數(shù),當(dāng)前偏移4+4=8,滿足,`c`在偏移8。-`d`(char,1字節(jié)):偏移8+8=16,對(duì)齊1,滿足。-`e`(int,4字節(jié)):需偏移量是4的倍數(shù),當(dāng)前偏移16+1=17,填充3字節(jié)(偏移20),`e`在偏移20。-`f`(long,8字節(jié)):需偏移量是8的倍數(shù),當(dāng)前偏移20+4=24,滿足,`f`在偏移24。結(jié)構(gòu)體總大?。?4+8=32字節(jié)。最大對(duì)齊數(shù)是8(long的大小),32是8的倍數(shù),無需額外填充。答案:結(jié)構(gòu)體`Example`的大小為32字節(jié)。驗(yàn)證:各成員偏移量為0(a)、4(b)、8(c)、16(d)、20(e)、24(f),總大小24+8=32。8.野指針的產(chǎn)生與避免題目:列舉野指針的三種常見產(chǎn)生原因,并說明至少兩種避免方法。解析:野指針指指向無效內(nèi)存的指針,無法通過簡(jiǎn)單判空(`nullptr`)檢測(cè)。答案:產(chǎn)生原因:1.指針未初始化:定義指針變量后未賦值,默認(rèn)指向隨機(jī)內(nèi)存(如`intp;p=10;`)。2.指針指向的內(nèi)存被釋放后未置空:`deletep`后,`p`成為懸空指針(danglingpointer),若后續(xù)再次訪問`p`即形成野指針。3.指針越界訪問:如訪問數(shù)組`arr[10]`時(shí),指針指向`arr[10]`(假設(shè)數(shù)組大小為10,索引0-9),超出有效范圍。避免方法:1.指針初始化時(shí)賦值為`nullptr`(或有效地址),避免未初始化。2.釋放內(nèi)存后立即將指針置為`nullptr`(如`deletep;p=nullptr;`),后續(xù)訪問時(shí)可通過`if(p)`判斷是否有效。3.使用智能指針(如`std::unique_ptr`、`std::shared_ptr`)自動(dòng)管理內(nèi)存生命周期,避免手動(dòng)釋放。4.避免返回局部變量的指針或引用(局部變量生命周期結(jié)束后內(nèi)存被回收)。9.const與volatile的聯(lián)合使用題目:說明`constvolatileintp`的含義,并舉例說明其使用場(chǎng)景。解析:`const`修飾指針指向的內(nèi)容不可修改(但指針本身可修改),`volatile`修飾指針指向的內(nèi)容可能被編譯器未知的因素(如硬件、其他線程)修改,禁止編譯器優(yōu)化對(duì)該變量的讀取。答案:`constvolatileintp`表示`p`是一個(gè)指向`constvolatileint`的指針。指針本身可以修改(非`const`),但指針指向的內(nèi)容既不可被當(dāng)前代碼修改(`const`),又可能被外部因素修改(`volatile`),因此每次訪問都需從內(nèi)存讀取,不能緩存。使用場(chǎng)景:訪問硬件寄存器(如嵌入式系統(tǒng)中的只讀狀態(tài)寄存器)。例如,某硬件狀態(tài)寄存器的值由外部電路更新(如傳感器數(shù)據(jù)),程序只能讀取不能修改,此時(shí)可用`constvolatileint`指針指向該寄存器地址,確保編譯器不優(yōu)化讀取操作,且防止程序誤修改。示例代碼:```cpp//假設(shè)硬件狀態(tài)寄存器地址為0x1000,只讀且值可能被硬件修改constvolatileintstatus_reg=reinterpret_cast<constvolatileint>(0x1000);intget_status(){returnstatus_reg;//每次讀取都從內(nèi)存(寄存器)獲取最新值,不使用緩存}```

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論