C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案
一、【阿里C++面試題】
1、如何初始化一個指針數組。
答案:
c++中的指針是一個很經典的用法,但是也是最容易出錯的,比如定義了一個指針,必須對其進行初始化,不然這個指針指向的是一個未知的內存地址,后續對其操作的時候,會報錯。這只是其次,最讓人頭疼的就是指針錯誤問題,往往編譯的時候可以通過,在程序運行的時候,就會出現異常,如果對程序不是很熟悉,則不是很容易找到問題所在,我最近就遇到過很多這樣的問題,定義了一個結構體指針,使用的時候忘記初始化,導致在后邊使用的時候程序報異常。下面就總結一下c++指針初始化的一些方法,
以及我自己遇到的一些問題以及心得體會。
一.c++指針初始化的一般方法:
1.將一個已經在內存中存在變量的地址傳遞給定義的指針,這個指針就指向這個變量的內存地址(相同的數據類型),完成初始化。
比如:
int a=2; int *b=&a;2.利用new開辟一塊地址空間
struct test{int a;int b; }*t;void main() {int c=0;test *t=new test();c=t->a; }使用 new開辟的空間,記得使用delete釋放,因為new出來的是返回的堆的空間,堆的空間是不會自動釋放的,存放變量的棧才會自動釋放。delete釋放其實只是釋放了申請的這塊內存空間,但是指針并沒有沒撤銷,指針還是指向這塊地址,但是不可用(靠人品吃飯的有可能可以用),是非法的。所以用delete釋放掉一塊堆內存時,應該自己手動將指針設置為NULL。
3.把指針設置為NULL或者0
這樣做一般只是為了沒有具體初始化的時候做的,這樣避免了野指針,后面可以使用if(指針==NULL)來判斷,然后再進行操作。
錯題解析:首先明確一個概念,就是指向數組的指針,和存放指針的數組。 指向數組的指針:char (*array)[5];含義是一個指向存放5個字符的數組的指針。 存放指針的數組:char *array[5];含義是一個數組中存放了5個指向字符型數據的指針。 按照題意,我理解為初始化一個存放指針的數組,char *array[2]={“China”,”Beijing”};其含義是初始化了一個有兩個指向字符型數據的指針的數組,這兩個指針分別指向字符串”China”和”Beijing”。
2、關鍵字const是什么含意?
正確答案:
在標準C++中,這樣定義的是一個常量,用來修飾內置類型變量,自定義對象,成員函數,返回值,函數參數。
const使用(類型):
1、用于指針的兩種情況:const是一個左結合的類型修飾符.
int const*A;//A可變,A不可變
intconst A;//A不可變,*A可變
2、限定函數的傳遞值參數:
void function(const int Var);//傳遞過來的參數在函數內不可以改變.
3、限定函數返回值型.
const int function();//此時const無意義
const myclassname function();//函數返回自定義類型myclassname.
4、限定函數類型.
void function()const;//常成員函數,常成員函數是不能改變成員變量值的函數。
錯題解析:我只要一聽到被面試者說:“const意味著常數”,我就知道我正在和一個業余者打交道。去年Dan Saks已經在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什么和不能做什么.如果你從沒有讀到那篇文章,只要能說出const意味著“只讀”就可 以了。盡管這個答案不是完全的答案,但我接受它作為一個正確的答案。(如果你想知道更詳細的答案,仔細讀一下Saks的文章吧。)如果應試者能正確回答這 個問題,我將問他一個附加的問題:下面的聲明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作用是一樣,a是一個常整型數。第三個意味著a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個意思a是一個指向整 型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。最后一個意味著a是一個指向常整型數的常指針(也就是說,指針指向的整型 數是不可修改的,同時指針也是不可修改的)。如果應試者能正確回答這些問題,那么他就給我留下了一個好印象。順帶提一句,也許你可能會問,即使不用關鍵字 const,也還是能很容易寫出功能正確的程序,那么我為什么還要如此看重關鍵字const呢?我也如下的幾下理由: 1). 關鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。如果你曾花很多時間清理 其它人留下的垃圾,你就會很快學會感謝這點多余的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。) 2). 通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。 3). 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。
3、 什么是動態特性?
正確答案:
在絕大多數情況下,程序的功能是在編譯的時候就確定下來的,我們稱為靜態特性。反之,如果程序的功能是在運行時刻才確定下來的,則稱為動態特性。
動態特性是面向對象語言最強大的功能之一,因為它在語言層面上支持程序的可擴展性,而可擴展性是軟件設計追求的重要目標之一。
c++虛函數、抽象基類、動態綁定、多態構成了出色的動態特性。
1.虛函數
假定幾何形狀的基類為Shape,其派生類有Circle、Rectangle、Ellipse等,每個派生類都能夠繪制自己所代表的形狀。不管派生類的形狀如何,我們希望用統一的方式來調用繪制函數,最好是使用Shape定義的接口函數Draw(),并讓程序在運行是動態地確定應該使用哪一個派生類的Draw()函數。
為了使這種行為可行,我們把基類Shape中的函數Draw()聲明為虛函數,然后在派生類中重新定義Draw()使之繪制正確的形狀,這種方法叫覆蓋,虛函數的聲明方法是在基類的函數原型之前加上關鍵之virtual。
一旦類的一個函數被聲明為虛函數,那么其派生類的對應函數也自動成為虛函數,這樣一級一級傳遞下去。
2.抽象基類
當我們把類看成是一種數據類型時,通常會認為該類肯定是要被實例為一個或多個對象的。但是在很多情況下,定義那些不能實例化出對象的類也是很有用的,這種類就稱為抽象類。抽象類的唯一目的就是讓其派生類繼承并實現它的接口方法,因此它通常也被稱為抽象基類。
如果將基類的虛函數聲明為春虛函數,那么該類就被定義為了抽象基類。純虛函數是在聲明時將其“初始化”為0的函數,例如:
class Shape { //Shape是抽象基類public:virtual void Draw(void)=0; //Draw()為純虛函數}`抽象基類Shape的純虛函數Draw()根本不知道自己應該怎么繪制出一個“形狀”來,具體功能必須有代表具體形狀的派生類對應的Draw()函數來實現。
我們知道,函數名就是函數的地址,將一個函數初始化為0意味著函數的地址將為0,這就是在告訴編譯器,不要為該函數編址,從而阻止該類的實例化行為。
抽象基類的主要用途是“接口與實現分離”;不僅要把數據成員(信息)隱藏起來,而且還要把實現完全隱藏起來,只留一些接口給外部調用。
錯題解析:在絕大多數情況下, 程序的功能是在編譯的時候就確定下來的, 我們稱之為靜態特性。 反之, 如果程序的功能是在運行時刻才能確定下來的, 則稱之為動態特性。C++中, 虛函數,抽象基類, 動態綁定和多態構成了出色的動態特性。
4、基類的有1個虛函數,子類還需要申明為virtual嗎?為什么。
正確答案:建議加上vitrual,代碼是寫給人看的
錯題解析:不申明沒有關系的。 不過,我總是喜歡顯式申明,使得代碼更加清晰。
5、在C++ 程序中調用被 C 編譯器編譯后的函數,為什么要加 extern “C”聲明?
正確答案:
c語言程序和c++程序在編譯時,是相互獨立的編譯;在.c文件中,編譯器將Add函數重命名為_Add; 而在.cpp文件中,編譯器將用extern聲明的函數重命名為(?Add@@YAHHH@Z);那么在鏈接階段,在_mian函數中該Add函數被調用;
此時編譯器帶著(?Add@@YAHHH@Z)函數名進入test.c文件的編譯文件中去尋找(?Add@@YAHHH@Z)函數,但是在test.c文件中這個Add函數被編譯器重命名為_Add,由于在.cpp文件中和.c文件中同一個函數名被編譯器重命名后的名字不一樣;所以.cpp文件聲明的外部函數找不到真正定義的地方;程序錯誤;
(2)使用extern “C” int Add(int,int); 外部函數—-正確
解釋:
c++語言為了支持重載,對編譯時函數的重命名規則進行更改,
使用extern “C” 的方式在c++程序中聲明c語言文件中的函數,可以在編譯時,告訴編譯器使用C語言的規則對該函數的的函數名的進行重命名,這樣在鏈接的時候,就可以順利在.c文件中找到該函數;
錯題解析:函數和變量被C++編譯后在符號庫中的名字與C語言的不同,被extern “C”修飾的變量和函數是按照C語言方式編譯和連接的。由于編譯后的名字不同,C++程序不能直接調用C 函數。C++提供了一個C 連接交換指定符號extern“C”來解決這個問題。
6、如何定義Bool變量的TRUE和FALSE的值。
正確答案:
對于C語言,并不存在系統自帶的bool類型和False和Ture的定義,如果要使用則必須自定義類型。
有兩種常見的方法。
1、使用宏定義。
通過define來進行定義False和True。可以采用如下方式:
(1) 直接定義數值
(2) 通過邏輯判斷定義
#define False (1!=1) #define True (1==1)2、使用枚舉定義。
這種方法可以同時定義類型BOOL
錯題解析:不知道這個題有什么陷阱,寫到現在神經已經大了,一般來說先要把TURE和FALSE給定義了,使用#define就可以: #define TURE 1 #define FALSE 0 如果有一個變量需要定義成bool型的,舉個例子:bool a=TURE;就可以了。
7、內聯函數INline和宏定義一起使用的區別。
正確答案:
1、宏定義不會進行類型的判斷,只是單存的替換文本;
inline會對參數類型進行判斷。
2、宏不是函數,inline修飾的是函數。
3、宏返回值不能強制轉換成合適的類型,inline返回值可以。
錯題解析:內聯函數是在編譯的時候已經做好將對應的函數代碼替換嵌入到對應的位置,適用于代碼較少的函數。 宏定義是簡單的替換變量,如果定義的是有參數的函數形式,參數不做類型校驗。
8、編寫my_strcpy函數,實現與庫函數strcpy類似的功能,不能使用任何庫函數;
正確答案:
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
returnstrDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘’);
returntempptr ;
}
9、 完成程序,實現對數組的降序排序
#include
void sort(int array[] );
int main()
{
int array[]={45,56,76,234,1,34,23,2,3}; //數字任//意給出
sort( array );
return 0;
}
void sort( int array[] )
{____________________________________
inti,j,k;
for(i=1;i<=7;i++) { if(array[i]>array[i-1])
{
k=ARRAY[i];
j=i-1;
do
{
array[j+1]=array[j];
j– ;
}
while(k>array[j]&&j>=0);
array[j+1]=k;
}
}
—————————————————–
}
10、ICMP是什么協議,處于哪一層?
正確答案:
Internet控制報文協議,處于網絡層(IP層)
11、 C中static有什么作用
正確答案:
(1)隱藏。 當我們同時編譯多個文件時,所有未加static前綴的全局變量和函數都具有全局可見性,故使用static在不同的文件中定義同名函數和同名變量,而不必擔心命名沖突。
(2)static的第二個作用是保持變量內容的持久。存儲在靜態數據區的變量會在程序剛開始運行時就完成初始化,也是唯一的一次初始化。共有兩種變量存儲在靜態存儲區:全局變量和static變量。
(3)static的第三個作用是默認初始化為0.其實全局變量也具備這一屬性,因為全局變量也存儲在靜態數據區。在靜態數據區,內存中所有的字節默認值都是0×00,某些時候這一特點可以減少程序員的工作量。
12、
Void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, “hello”);
printf(str);
}
請問運行Test函數會有什么樣的結果?
正確答案:
可以運行
13、C++特點是什么,如何實現多態?畫出基類和子類在內存中的相互關系。
正確答案:
多態的基礎是繼承,需要虛函數的支持,簡單的多態是很簡單的。 子類繼承父類大部分的資源,不能繼承的有構造函數,析構函數,拷貝構造函數,operator=函數,友元函數等等
14、 C++中的什么是多態性? 是如何實現的?
正確答案:
多態性是面向對象程序設計語言繼數據抽象和繼承之后的第三個基本特征。它是在運行時出現的多態性通過派生類和虛函數實現。基類和派生類中使用同樣的函數名, 完成不同的操作具體實現相隔離的另一類接口,即把" w h a t"從"h o w"分離開來。多態性提高了代碼的組織性和可讀性,虛函數則根據類型的不同來進行不同的隔離。
15、 關鍵字static的作用是什么?
正確答案:
這個簡單的問題很少有人能回答完全。在C語言中,關鍵字static有三個明顯的作用:
1). 在函數體,一個被聲明為靜態的變量在這一函數被調用過程中維持其值不變。
2). 在模塊內(但在函數體外),一個被聲明為靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。
3). 在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。 大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個應試者的嚴重的缺點,因為他顯然不懂得本地化數 據和代碼范圍的好處和重要性。
16、#define MAX_LEN 500 char arry[MAX_LEN]; cin>>arry; 這段代碼有問題嗎?若有,請指出并修改;
正確答案:
有問題。頭文件缺少。 #include
17、delete []arry 和 delete arry 一樣嗎?不一樣請說明;
正確答案:
delete []arry 釋放的是多個同一類型的地址空間 Delete[]arry 釋放的是一個某種類型的地址空間
18、 多態的作用?
正確答案:
主要是兩個:
1)隱藏實現細節,使得代碼能夠模塊化;擴展代碼模塊,實現代碼重用;
2)接口重用,為了類在繼承和派生的時候,保證使用家族中任一類的實例的某一屬性時的正確調用。
19、C語言的volatile的含義是什么。使用時會對編譯器有什么暗示。
正確答案:
從詞面上講,volatile的意思是易變的,也就是說,在程序運行過程中,有一些變量可能會被莫名其妙的改變,而優化器為了節約時間,有時候不會重讀這個變量的真實值,而是去讀在寄存器的備份,這樣的話,這個變量的真實值反而被優化器給“優化”掉了,用時髦的詞說就是被“和諧”了。如果使用了這個修飾詞,就是通知編譯器別犯懶,老老實實去重新讀一遍!可能我說的太“通俗”了,那么我引用一下“大師”的標準解釋: volatile的本意是“易變的” 。 由于訪問寄存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化,但有可能會讀臟數據。當要求使用volatile 聲明的變量的值的時候,系統總是重新從它所在的內存讀取數據,即使它前面的指令剛剛從該處讀取過數據。而且讀取的數據立刻被保存。 精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。 下面是volatile變量的幾個例子:
1). 并行設備的硬件寄存器(如:狀態寄存器)
2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
3). 多線程應用中被幾個任務共享的變量 嵌入式系統程序員經常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內容將會帶來災難。
20、 請簡述以下兩個for循環的優缺點
1)for (i=0; i<n; i++)
{
if (condition)
DoSomething();
else
DoOtherthing();
}
2)if (condition)
{
for (i=0; i<n; i++)
DoSomething();
}
else
{
for (i=0; i<n; i++)=“” dootherthing();=“” }=“”
正確答案:
1)優點:程序簡潔。=“” 缺點:多執行了n-1次邏輯判斷,并且打斷了循環“流水線”作業,使得編譯器不能對循環進行優化處理,降低了效率。=“”
2)優點:循環的效率高。缺點:程序不簡潔。="
二、【百度C++面試題】
1、 預處理器標識#error的目的是什么?
正確答案:
如果你不知道答案,請看參考文獻1。
2、C語言的volatile的含義是什么。使用時會對編譯器有什么暗示。
正確答案:
從詞面上講,volatile的意思是易變的,也就是說,在程序運行過程中,有一些變量可能會被莫名其妙的改變,而優化器為了節約時間,有時候不會重讀這個變量的真實值,而是去讀在寄存器的備份,這樣的話,這個變量的真實值反而被優化器給“優化”掉了,用時髦的詞說就是被“和諧”了。如果使用了這個修飾詞,就是通知編譯器別犯懶,老老實實去重新讀一遍!可能我說的太“通俗”了,那么我引用一下“大師”的標準解釋: volatile的本意是“易變的” 。 由于訪問寄存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化,但有可能會讀臟數據。當要求使用volatile 聲明的變量的值的時候,系統總是重新從它所在的內存讀取數據,即使它前面的指令剛剛從該處讀取過數據。而且讀取的數據立刻被保存。 精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。 下面是volatile變量的幾個例子: 1). 并行設備的硬件寄存器(如:狀態寄存器) 2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables) 3). 多線程應用中被幾個任務共享的變量 嵌入式系統程序員經常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內容將會帶來災難。
3、 MFC中CString是類型安全類么?
正確答案:
不是,其它數據類型轉換到CString可以使用CString的成員函數Format來轉換
4、內聯函數INline和宏定義一起使用的區別。
正確答案:
內聯函數是在編譯的時候已經做好將對應的函數代碼替換嵌入到對應的位置,適用于代碼較少的函數。 宏定義是簡單的替換變量,如果定義的是有參數的函數形式,參數不做類型校驗。
5、C++中什么數據分配在棧或堆中,New分配數據是在近堆還是遠堆中?
正確答案:
棧: 存放局部變量,函數調用參數,函數返回值,函數返回地址。由系統管理 堆: 程序運行時動態申請,new 和 malloc申請的內存就在堆上
6、DB事務處理的四個特性:
正確答案:
原子性,一致性,隔離性,持久性 就答對一個:一致性,
7、如何初始化一個指針數組。
正確答案:
首先明確一個概念,就是指向數組的指針,和存放指針的數組。 指向數組的指針:char (*array)[5];含義是一個指向存放5個字符的數組的指針。 存放指針的數組:char *array[5];含義是一個數組中存放了5個指向字符型數據的指針。 按照題意,我理解為初始化一個存放指針的數組,char *array[2]={“China”,”Beijing”};其含義是初始化了一個有兩個指向字符型數據的指針的數組,這兩個指針分別指向字符串”China”和”Beijing”。
8、 int i=(j=4,k=8,l=16,m=32); printf(“%d”, i); 輸出是多少?
正確答案:
相當于 i=j=4;i=k=8;i=l=16;i=m=32; 故最后i=32;
9、如何在C中初始化一個字符數組。
正確答案:
這個問題看似很簡單,但是我們要將最簡單的問題用最嚴謹的態度來對待。關鍵的地方:初始化、字符型、數組。最簡單的方法是char array[];。這個問題看似解決了,但是在初始化上好像還欠缺點什么,個人認為:char array[5]={’1′,’2′,’3′,’4′,’5′};或者char array[5]={“12345″};或者char array[2][10]={“China”,”Beijing”};也許更符合“初始化”的意思。
10、參數傳遞有幾種方式;實現多態參數傳遞采用什么方式,如果沒有使用某種方式原因是什么;
正確答案:
傳值,傳指針或者引用
11、請填寫BOOL , float, 指針變量 與“零值”比較的 if 語句。
正確答案:
這里“零值”可以是0, 0.0 , FALSE或者“空指針”。例如 int 變量 n 與“零值”比較的 if 語句為:
12、C++特點是什么,如何實現多態?畫出基類和子類在內存中的相互關系。
正確答案:
多態的基礎是繼承,需要虛函數的支持,簡單的多態是很簡單的。 子類繼承父類大部分的資源,不能繼承的有構造函數,析構函數,拷貝構造函數,operator=函數,友元函數等等
13、 什么是“引用”?申明和使用“引用”要注意哪些問題?
正確答案:
引用就是某個目標變量的“別名”(alias),對應用的操作與對變量直接操作效果完全相同。申明一個引用的時候,切記要對其進行初始化。引 用聲明完畢后,相當于目標變量名有兩個名稱,即該目標原名稱和引用名,不能再把該引用名作為其他變量名的別名。聲明一個引用,不是新定義了一個變量,它只 表示該引用名是目標變量名的一個別名,它本身不是一種數據類型,因此引用本身不占存儲單元,系統也不給引用分配存儲單元。不能建立數組的引用。
14、觸發器怎么工作的?
正確答案:
觸發器主要是通過事件進行觸發而被執行的,當對某一表進行諸如UPDATE、 INSERT、 DELETE 這些操作時,數據庫就會自動執行觸發器所定義的SQL 語句,從而確保對數據的處理必須符合由這些SQL 語句所定義的規則。
15、C也可以通過精心封裝某些函數功能實現重用,那C++的類有什么優點嗎,難道僅僅是為實現重用。
正確答案:
并不僅僅是這樣的。 OOD,OOP從根本上改變了程序設計模式和設計思想,具備重大和深遠的意義。 類的三大最基本的特征:封裝,繼承,多態.
16、CSingleLock是干什么的。
正確答案:
同步多個線程對一個數據類的同時訪問
17、 C++中引用和指針的區別?
正確答案:
引用是對象的別名, 操作引用就是操作這個對象, 必須在創建的同時有效得初始化(引用一個有效的對象, 不可為NULL), 初始化完畢就再也不可改變, 引用具有指針的效率, 又具有變量使用的方便性和直觀性, 在語言層面上引用和對象的用法一樣, 在二進制層面上引用一般都是通過指針來實現的, 只是編譯器幫我們完成了轉換。 之所以使用引用是為了用適當的工具做恰如其分的事, 體現了最小特權原則。
18、 C與C++各自是如何定義常量的?有什么不同?
正確答案:
C中是使用宏#define定義, C++使用更好的const來定義。 區別: 1)const是有數據類型的常量,而宏常量沒有,編譯器可以對前者進行靜態類型安全檢查,對后者僅是字符替換,沒有類型安全檢查,而且在字符替換時可能會產生意料不到的錯誤(邊際效應)。 2)有些編譯器可以對const常量進行調試, 不能對宏調試。
19、 C++函數中值的傳遞方式有哪幾種?
正確答案:
C++函數的三種傳遞方式為:值傳遞、指針傳遞和引用傳遞。
20、一般數據庫若出現日志滿了,會出現什么情況,是否還能使用?
正確答案:
只能執行查詢等讀操作,不能執行更改,備份等寫操作,原因是任何寫操作都要記錄日志。也就是說基本上處于不能使用的狀態。
三、【騰訊C++面試題】
1、.C++里面如何聲明constvoidf(void)函數為C程序中的庫函數?
正確答案:
在該函數前添加extern “C”聲明。由于編譯后的名字不同,C++程序不能直接調用C 函數。
2、c++中類和c語言中struct的區別(至少兩點)
正確答案:
(1)c++中的類默認的成員是私有的,struct默認的是共有的。
(2)c++中的類可以定義成員函數,struct只能定義成員變量。
(3)C++中的類有繼承、多態的特性,struct沒有。
3、IP組播有那些好處?
正確答案:
Internet上產生的許多新的應用,特別是高帶寬的多媒體應用,帶來了帶寬的急劇消耗和網絡擁擠問題。組播是一種允許一個或多個發送者(組播源)發送單一的數據包到多個接收者(一次的,同時的)的網絡技術。組播可以大大的節省網絡帶寬,因為無論有多少個目標地址,在整個網絡的任何一條鏈路上只傳送單一的數據包。所以說組播技術的核心就是針對如何節約網絡資源的前提下保證服務質量。
4、變量的聲明和定義有什么區別?
正確答案:
聲明變量不分配空間,定義變量要分配空間。聲明主要是告訴編譯器,后面的引用都按聲明的格式。定義其實包含了聲明的意思,同時要分配內存空間。
5、程序什么時候應該使用線程,什么時候單線程效率高。
正確答案:
1 耗時的操作使用線程,提高應用程序響應
2 并行操作時使用線程,如C/S架構的服務器端并發線程響應用戶的請求。
3 多CPU系統中,使用線程提高CPU利用率
4 改善程序結構。一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利于理解和修改。
其他情況都使用單線程。
6、介紹一下模板和容器。如何實現?(也許會讓你當場舉例實現)
正確答案:
模板可以說比較古老了,但是當前的泛型編程實質上就是模板編程。 它體現了一種通用和泛化的思想。 STL有7種主要容器:vector,list,deque,map,multimap,set,multiset.
7、以下為WindowsNT下的32位C++程序,請計算sizeof的值
charstr[]=“Hello”;
charp=str;
intn=10;
//請計算
sizeof(str)=?
sizeof§=?
sizeof(n)=?
voidFunc(charstr[100])
{
//請計算
sizeof(str)=?
}
voidp=malloc(100);
//請計算
sizeof§=?
正確答案:
sizeof (str ) = 6
sizeof ( p ) = 4
sizeof ( n ) =4
void Func ( char str[100])
{
sizeof( str ) = 4
}
void *p = malloc( 100 );
sizeof ( p ) =4
8、C語言同意一些令人震驚的結構,下面的結構是合法的嗎,如果是它做些什么?inta=5,b=7,c;c=a+++b;
正確答案:
這個問題將做為這個測驗的一個愉快的結尾。不管你相不相信,上面的例子是完全合乎語法的。問題是編譯器如何處理它?水平不高的編譯作者實際上會爭論這個問題,根據最處理原則,編譯器應當能處理盡可能所有合法的用法。因此,上面的代碼被處理成: c = a++ + b; 因此, 這段代碼持行后a = 6, b = 7, c = 12。 如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個當作問題。我發現這個問題的最大好處是:這是一個關于代碼編寫風格,代碼的可讀性,代碼的可修改性的好的話題
9、#include與#include“file.h”的區別?
正確答案:
前者是從Standard Library的路徑尋找和引用file.h,而后者是從當前工作路徑搜尋并引用file.h。
10、如何在C中初始化一個字符數組。
正確答案:
這個問題看似很簡單,但是我們要將最簡單的問題用最嚴謹的態度來對待。關鍵的地方:初始化、字符型、數組。最簡單的方法是char array[];。這個問題看似解決了,但是在初始化上好像還欠缺點什么,個人認為:char array[5]={’1′,’2′,’3′,’4′,’5′};或者char array[5]={“12345″};或者char array[2][10]={“China”,”Beijing”};也許更符合“初始化”的意思。
11、在C++程序中調用被C編譯器編譯后的函數,為什么要加extern“C”?
正確答案:
extern是C/C++語言中表明函數和全局變量作用范圍(可見性)的關鍵字,其聲明的函數和變量可以在本模塊或其它模塊中使用。 通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數和全局變量以關鍵字extern聲明。
12、內存的分配方式的分配方式有幾種?
正確答案:
1)從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量。
2)在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
3)從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多。
13、在C++程序中調用被C編譯器編譯后的函數,為什么要加extern"C"?
正確答案:
C++語言支持函數重載,C語言不支持函數重載。函數被C++編譯后在庫中的名字與C語言的不同。假設某個函數的原型為: void foo(int x, int y);該函數被C編譯器編譯后在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。C++提供了C連接交換指定符號extern"C"來解決名字匹配問題。
14、如何讓局部變量具有全局生命期。
正確答案:
具體的生命期的概念我覺得我還要好好深入的學習一下,但是這個題目還算比較簡單,即用static修飾就可以了,但是只是生命期延長,范圍并沒有擴大,除非把這個變量定義在函數體外的靜態區,不過那樣就變成全局變量了,仿佛不符合題目要求。
15、解釋堆和棧的區別。
正確答案:
具體的生命期的概念我覺得我還要好好深入的學習一下,但是這個題目還算比較簡單,即用static修飾就可以了,但是只是生命期延長,范圍并沒有擴大,除非把這個變量定義在函數體外的靜態區,不過那樣就變成全局變量了,仿佛不符合題目要求。
16、在C++程序中調用被C編譯器編譯后的函數,為什么要加extern“C”聲明?
正確答案:
函數和變量被C++編譯后在符號庫中的名字與C語言的不同,被extern “C”修飾的變量和函數是按照C語言方式編譯和連接的。由于編譯后的名字不同,C++程序不能直接調用C 函數。C++提供了一個C 連接交換指定符號extern“C”來解決這個問題。
17、strtok函數在使用上要注意什么問題。
正確答案:
這個問題我不知道能不能回答全面,因為實在是用的很少。這個函數的作用是分割字符串,但是要分割的字符串不能是常量,這是要注意的。比如先定義一個字符串:char array[]=”part1,part2″;,strtok的原形是char *strtok(char *string, char *delim);,我們將”,”作為分隔符,先用pt=strtok(array,”,”);,得到的結果print出來就是”part1″,那后面的呢,要寫成pt=strtok(NULL,”,”);,注意,要用NULL,如果被分割的字符串會被分成N段,那從第二次開始就一直要用NULL。總結起來,需要注意的是:被分割的字符串和分隔符都要使用變量;除第一次使用指向字符串的指針外,之后的都要使用NULL;注意使用這個函數的時候千萬別把指針跟丟了,不然就全亂了。
18、用預處理指令#define聲明一個常數,用以表明1年中有多少秒(忽略閏年問題)
正確答案:
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在這想看到幾件事情:
1). #define 語法的基本知識(例如:不能以分號結束,括號的使用,等等)
2). 懂得預處理器將為你計算常數表達式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。 3). 意識到這個表達式將使一個16位機的整型數溢出-因此要用到長整型符號L,告訴編譯器這個常數是的長整型數。
4). 如果你在你的表達式中用到UL(表示無符號長整型),那么你有了一個好的起點。記住,第一印象很重要。
19、說一說C與C++的內存分配方式?
正確答案:
1)從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在,如全局變量,static變量。
2)在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
3)從堆上分配(動態內存分配)程序在運行的時候用malloc或new申請任意多少的內存,程序員負責在何時用free或delete釋放內存。動態內存的生存期自己決定,使用非常靈活。
20、你如何理解MVC。簡單舉例來說明其應用。
正確答案:
MVC模式是observer 模式的一個特例,典型的有MFC里面的文檔視圖架構。
四、【華為C++面試題】
1、在C++程序中調用被C編譯器編譯后的函數,為什么要加extern“C”聲明?
正確答案:
二者的編譯器不同
2、inti=(j=4,k=8,l=16,m=32);printf(“%d”,i);輸出是多少?
正確答案:
相當于i=j=4;i=k=8;i=l=16;i=m=32;故最后i=32;
3、#include與#include“file.h”的區別?
正確答案:
相當于i=j=4;i=k=8;i=l=16;i=m=32;故最后i=32;
4、既然C++中有更好的const為什么還要使用宏?
正確答案:
相當于i=j=4;i=k=8;i=l=16;i=m=32;故最后i=32;
5、重載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區別?
正確答案:
從定義上來說:重載:是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。重寫:是指子類重新定義復類虛函數的方法。從實現原理上來說:重載:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然后這些同名函數就成了不同的函數。重寫:當子類重新定義了父類的虛函數后,父類指針根據賦給它的不同的子類指針,動態的調用屬于子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。
6、C++和C定義結構的分別是什么。
正確答案:
Clanguage的結構僅僅是數據的結合Cplusplus的struct和class其實具備幾乎一樣的功能,只是默認的訪問屬性不一樣而已。
7、#include和#include"a.h"有什么區別?
正確答案:
對于#include,編譯器從標準庫路徑開始搜索a.h對于#include"a.h",編譯器從用戶的工作路徑開始搜索a.h
8、#include和#include“filename.h”有什么區別?
正確答案:
前者用來包含開發環境提供的庫頭文件,后者用來包含自己編寫的頭文件。
9、C函數可否單獨編譯?
正確答案:
外部函數,可以在開始引進來
10、請簡述以下兩個for循環的優缺點
1)for(i=0;i<n;i++)
{
if(condition)
DoSomething();
else
DoOtherthing();
}
2)if(condition)
{
for(i=0;i<n;i++)
DoSomething();
}
else
{
for(i=0;i<n;i++)=““dootherthing();=””}=“”
正確答案:
1)優點:程序簡潔。缺點:多執行了n-1次邏輯判斷,并且打斷了循環“流水線”作業,使得編譯器不能對循環進行優化處理,降低了效率。
2)優點:循環的效率高。缺點:程序不簡潔。
11、完成程序,實現對數組的降序排序
#include
voidsort(intarray[]);
intmain()
{
intarray[]={45,56,76,234,1,34,23,2,3};//數字任//意給出
sort(array);
return0;
}
voidsort(intarray[])
{____________________________________
inti,j,k;
for(i=1;i<=7;i++){if(array[i]>array[i-1])
{
k=ARRAY[i];
j=i-1;
do
{
array[j+1]=array[j];
j–;
}
while(k>array[j]&&j>=0);
array[j+1]=k;
}
}
—————————————————–
}
12、delete[]arry和deletearry一樣嗎?不一樣請說明;
正確答案:
delete[]arry釋放的是多個同一類型的地址空間Delete[]arry釋放的是一個某種類型的地址空間
13、結合1個你認為比較能體現OOP思想的項目,用UML來描述。
正確答案:
(最好這個項目繼承,多態,虛函數都有體現)這個問題大概會占面試時間的一半,并且會問很多問題,一不小心可能會被問住)
14、C與C++各自是如何定義常量的?有什么不同?
正確答案:
C中是使用宏#define定義,C++使用更好的const來定義。區別:1)const是有數據類型的常量,而宏常量沒有,編譯器可以對前者進行靜態類型安全檢查,對后者僅是字符替換,沒有類型安全檢查,而且在字符替換時可能會產生意料不到的錯誤(邊際效應)。2)有些編譯器可以對const常量進行調試,不能對宏調試。
15、頭文件中的ifndef/define/endif干什么用?
正確答案:
防止重復定義
16、C++中為什么用模板類。
正確答案:
(1)可用來創建動態增長和減小的數據結構
(2)它是類型無關的,因此具有很高的可復用性。
(3)它在編譯時而不是運行時檢查數據類型,保證了類型安全
(4)它是平臺無關的,可移植性
(5)可用于基本數據類型
17、動態連接庫的兩種方式?
正確答案:
調用一個DLL中的函數有兩種方法:1載入時動態鏈接(load-timedynamiclinking),模塊非常明確調用某個導出函數,使得他們就像本地函數一樣。這需要鏈接時鏈接那些函數所在DLL的導入庫,導入庫向系統提供了載入DLL時所需的信息及DLL函數定位。2運行時動態鏈接(run-timedynamiclinking),運行時可以通過LoadLibrary或LoadLibraryEx函數載入DLL。DLL載入后,模塊可以通過調用GetProcAddress獲取DLL函數的出口地址,然后就可以通過返回的函數指針調用DLL函數了。如此即可避免導入庫文件了。
18、在什么時候需要使用“常引用”?
正確答案:
如果既要利用引用提高程序的效率,又要保護傳遞給函數的數據不在函數中被改變,就應使用常引用。常引用聲明方式:const類型標識符&引用名=目標變量名;
19、預處理器標識#error的目的是什么?
正確答案:
如果你不知道答案,請看參考文獻1。這問題對區分一個正常的伙計和一個書呆子是很有用的。只有書呆子才會讀C語言課本的附錄去找出象這種問題的答案。當然如果你不是在找一個書呆子,那么應試者最好希望自己不要知道答案。
20、GCC3.2.2版本中支持哪幾種編程語言。
正確答案:
這個問題實在變態,就像問你#error的作用是什么一樣。不可否認,gcc是linux下一個亮點,是一個備受無數程序員推崇的編譯器,其優點省略1000字,有興趣可以自己查,我翻了翻書,書上曰:支持C,C++,Java,Obj-C,Ada,Fortran,Pascal,Modula-3等語言,這個“等”比較要命,不過我認為已經很全了,如果認為還是不全,干脆把ASM也加上算了,不過那已經不算是編譯了。
五、【小米C++面試題】
1、已知strcpy的函數原型:charstrcpy(charstrDest,constchar*strSrc)其中strDest是目的字符串,strSrc是源字符串。不調用C++/C的字符串庫函數,請編寫函數strcpy。
正確答案:
charstrcpy(charstrDest,constcharstrSrc)
{
if(strDestNULL||strSrcNULL)
returnNULL;
if(strDest==strSrc)
returnstrDest;
chartempptr=strDest;
while((*strDest++=*strSrc++)!=‘\0’)
;
returntempptr;
}
2.請問運行Test函數會有什么樣的結果?
charGetMemory(void)
{
charp[]=“helloworld”;
returnp;
}
voidTest(void)
{
charstr=NULL;
str=GetMemory();
printf(str);
}
正確答案:亂碼
3、重載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區別?
正確答案:
從定義上來說:重載:是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。重寫:是指子類重新定義復類虛函數的方法。從實現原理上來說:重載:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然后這些同名函數就成了不同的函數。重寫:當子類重新定義了父類的虛函數后,父類指針根據賦給它的不同的子類指針,動態的調用屬于子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。
4、多重繼承如何消除向上繼承的二義性。
正確答案:
使用虛擬繼承即可.
5、#include與#include“file.h”的區別?
正確答案:
前者是從StandardLibrary的路徑尋找和引用file.h,而后者是從當前工作路徑搜尋并引用file.h。
6、對數據庫的一張表進行操作,同時要對另一張表進行操作,如何實現?
正確答案:
將操作多個表的操作放入到事務中進行處理
7、#include<filename.h>和#include“filename.h”有什么區別?
正確答案:
查找范圍不同,后者先查找工作路徑,再查找VC標準路徑;前者只查工作路徑。
8、預處理器標識#error的目的是什么?
正確答案:
如果你不知道答案,請看參考文獻1。這問題對區分一個正常的伙計和一個書呆子是很有用的。只有書呆子才會讀C語言課本的附錄去找出象這種問題的答案。當然如果你不是在找一個書呆子,那么應試者最好希望自己不要知道答案。
9、頭文件的作用是什么?
正確答案:
1)通過頭文件來調用庫功能。
2)頭文件能加強類型安全檢查。
10、請問運行Test函數會有什么樣的結果?
voidGetMemory(charp)
{
p=(char)malloc(100);
}
voidTest(void)
{
char*str=NULL;
GetMemory(str);
strcpy(str,“helloworld”);
printf(str);
}
正確答案:
程序崩潰了
11、delete[]arry和deletearry一樣嗎?不一樣請說明;
正確答案:
delete[]arry釋放的是多個同一類型的地址空間Delete[]arry釋放的是一個某種類型的地址空間
12、請問運行Test函數會有什么樣的結果?
VoidGetMemory(char**p,intnum){
p=(char)malloc(num);
}
voidTest(void){
char*str=NULL;
GetMemory(&str,100);
strcpy(str,“hello”);
printf(str);
}
正確答案:
輸出“hello”
13、請簡述以下兩個for循環的優缺點
//第一個
for(i=0;i<N;i++)
{
if(condition)
DoSomething();
else
DoOtherthing();
}
//第二個
if(condition)
{
for(i=0;i<N;i++)
DoSomething();
}
else
{
for(i=0;i<N;i++)
DoOtherthing();
}
正確答案:
先循環再判斷,先判斷再循環第一個優點:每個循環都先判斷,再執行第二個優點:條件判斷,只發生其中一個行為
14、構造函數可否是虛汗數,為什么?析構函數呢,可否是純虛的呢?
正確答案:
錯題解析:構造函數不能為虛函數,要構造一個對象,必須清楚地知道要構造什么,否則無法構造一個對象。析構函數可以為純虛函數。
15、在C++程序中調用被C編譯器編譯后的函數,為什么要加extern"C"?
正確答案:
C++語言支持函數重載,C語言不支持函數重載。函數被C++編譯后在庫中的名字與C語言的不同。假設某個函數的原型為:voidfoo(intx,inty);該函數被C編譯器編譯后在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。C++提供了C連接交換指定符號extern"C"來解決名字匹配問題。
16、請寫出下面代碼在32位平臺上的運行結果,并說明sizeof的性質:
#include
#include
intmain(void)
{
chara[30];
charb=(char)malloc(20sizeof(char));
printf(“%d\n”,sizeof(a));
printf(“%d\n”,sizeof(b));
printf(“%d\n”,sizeof(a[3]));
printf(“%d\n”,sizeof(b+3));
printf(“%d\n”,sizeof((b+4)));
return0;
}
正確答案:
在32位系統下(如WIN32),指針長度為32位。a是一個有30個元素的字符型數組;b是一個字符串指針;a[3]是字符型;b+3是指針;*(b+4)是字符型。因此輸出:30、4、1、4、1
17、高級通信包括信號量,——-,——–
正確答案:
通常把信號、信號量通信稱為低級通信,而把管道、消息隊列、共享存儲區通信稱為高級通信,這個題目我也不知道怎么填了,。。。。。。
18、關聯、聚合(Aggregation)以及組合(Composition)的區別?
正確答案:
涉及到UML中的一些概念:關聯是表示兩個類的一般性聯系,比如“學生”和“老師”就是一種關聯關系;聚合表示has-a的關系,是一種相對松散的關系,聚合類不需要對被聚合類負責,如下圖所示,用空的菱形表示聚合關系:從實現的角度講,聚合可以表示為:classA{…}classB{A*a;……}而組合表示contains-a的關系,關聯性強于聚合:組合類與被組合類有相同的生命周期,組合類要對被組合類負責,采用實心的菱形表示組合關系:實現的形式是:classA{…}classB{Aa;…}
19、盡管不像非嵌入式計算機那么常見,嵌入式系統還是有從堆(heap)中動態分配內存的過程的。那么嵌入式系統中,動態分配內存可能發生的問題是什么?
正確答案:
這里,我期望應試者能提到內存碎片,碎片收集的問題,變量的持行時間等等。這個主題已經在ESP雜志中被廣泛地討論過了(主要是選項:J.Plauger,他的解釋遠遠超過我這里能提到的任何解釋),所有回過頭看一下這些雜志吧!讓應試者進入一種虛假的安全感覺后,我拿出這么一個小節目:下面的代碼片段的輸出是什么,為什么?
charptr;
if((ptr=(char)malloc(0))==NULL)
puts(“Gotanullpointer”);
else
puts(“Gotavalidpointer”);
這是一個有趣的問題。最近在我的一個同事不經意把0值傳給了函數malloc,得到了一個合法的指針之后,我才想到這個問題。這就是上面的代碼,該代碼的輸出是“Gotavalidpointer”。
20、請問運行Test函數會有什么樣的結果?
voidTest(void){
charstr=(char)malloc(100);
strcpy(str,“hello”);
free(str);
if(str!=NULL){
strcpy(str,“world”);
printf(str);
}
}
正確答案:
錯題解析:輸出“world”
總結
以上是生活随笔為你收集整理的C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity用UnityWebReques
- 下一篇: c语言画伯努利分布图像,C++ - 随机