C/C++ 面試題記錄
1、new 、 delete 、 malloc 、 free 的區別與關系?
new / delete 是C++的運算符,malloc / free 是C的標準庫函數。
new會調用對象的構造函數,delete會調用對象的析構函數。它們都可用於動態申請內存和釋放內存。
對於非內部數據類型的對象而言,使用malloc / free 無法滿足動態對象的要求,對象在創建的時候要自動執行構造函數,在銷毀時要自動執行析構函數。
由於malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加於malloc/free。
2、C++是不是安全類型的?
不是;兩個不同類型的指針之間可以相互轉換(reinterpret cast)。 C# 是安全類型的。
3、const 與 #define 相比有何優點?
const 作用: 定義常量、修飾函數參數、修飾函數返回值。被const修飾的東西都受到強制保護,可以防止意外的修改。
const常量具有數據類型,而宏常量沒有數據類型。編譯器可以對const常量進行類型安全檢查,而#define只是進行字符替換,沒有類型安全檢查。
有些集成的調試工具可以對const常量進行調試,但不能對宏定義進行調試。
4、引用與指針的區別?
引用必須被初始化,指針不需要。
引用初始化以後不能修改,指針可以改變其所指的對象。
不存在指向空值的引用,但存在指向空值的指針。
5、 成員函數通過什麽來區分不同對象的成員數據?為什麽能夠區分?
通過this指針, 因為它指向的是對象的首地址。
6、什麽時候必須重新拷貝構造函數?
當構造函數涉及到動態存儲分配空間的時候,要自己編寫拷貝構造函數,並且要深拷貝。
7、靜態函數存在的意義?
靜態私有成員在類外不能被訪問,只能通過類的靜態成員函數來訪問。
8、不允許重載的5個運算符?
.*(成員指針訪問運算符)、 ::(域運算符)、 sizeof 、 ? : 、 .(成員訪問符)
9、流運算符為什麽不能通過類的成員函數重載?一般怎麽解決?
因為通過類的成員函數重載要求運算符的第一個操作數必須是自己, 而流運算符重載要求第一個操作數是流對象。一般通過友元來解決。
10、對象間是怎樣實現數據的共享的?
通過類的靜態成員變量來實現的。靜態成員變量占有自己獨立的空間不為某個對象所私有。
11、友元關系有什麽特性?
單向的,非傳遞的,不能繼承的。
12、const char *p, char * const p;的區別
如果const位於星號的左側,則const就是用來修飾指針所指向的變量,即指針指向為常量;
如果const位於星號的右側,const就是修飾指針本身,即指針本身是常量。
13、繼承優缺點。
1、類繼承是在編譯時刻靜態定義的,且可直接使用,
2、類繼承可以較方便地改變父類的實現。
缺點:
1、因為繼承在編譯時刻就定義了,所以無法在運行時刻改變從父類繼承的實現
2、父類通常至少定義了子類的部分行為,父類的任何改變都可能影響子類的行為
3、如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。這種依賴關系限制了靈活性並最終限制了復用性。
14、多態的作用?
1.隱藏實現細節,使得代碼能夠模塊化;擴展代碼模塊,實現代碼重用。
2.接口重用:為了類在繼承和派生的時候,保證使用家族中任一類的實例的某一屬性時的正確調用
15、析構函數為什麽要虛擬?
為了防止析構不徹底造成內存泄漏
16、如何引用一個已經定義過的全局變量?
可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個變寫錯了,那麽在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麽在編譯期間不會報錯,而在連接期間報錯。
17、用什麽函數開啟新進程、線程。
線程:CreateThread/AfxBeginThread等
進程:CreateProcess等
18、strcpy()和memcpy()的區別?
strcpy()和memcpy()都可以用來拷貝字符串,strcpy()拷貝以’\0’結束,但memcpy()必須指定拷貝的長度。
19、總結static的應用和作用?
(1)函數體內static變量的作用範圍為該函數體,不同於auto變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
(2)在模塊內的static全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明它的模塊內;
(4)在類中的static成員變量屬於整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的static成員函數屬於整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。
20、struct(結構) 和 union(聯合)的區別?
1. 結構和聯合都是由多個不同的數據類型成員組成, 但在任何同一時刻, 聯合中只存放了一個被選中的成員(所有成員共用一塊地址空間), 而結構的所有成員都存在(不同成員的存放地址不同)。
2. 對於聯合的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了, 而對於結構的不同成員賦值是互不影響的。
21、windows消息系統由哪幾部分構成?
1.消息隊列:操作系統負責為進程維護一個消息隊列;程序運行時不斷的從該消息隊列中獲取消息、處理消息。
2.消息循環:應用程序通過消息循環不斷地獲取消息、處理消息。
3.消息處理:消息循環負責將消息派發到相關的窗口上使用關聯的窗口過程函數進行處理。
22、winsock建立連接的主要實現步驟?
服務器端:socket()建立套接字,綁定(bind)並監聽(listen),用accept()等待客戶端連接, accept()發現有客戶端連接,建立一個新的套接字,自身重新開始等待連接。該新產生的套接字使用send()和recv()寫讀數據,直至數據交換完畢,closesocket()關閉套接字。
客戶端:socket()建立套接字,連接(connect)服務器,連接上後使用send()和recv(),在套接字上寫讀數據,直至數據交換完畢,closesocket()關閉套接字。
23、進程間通信的主要方式
信號量、管道、消息、共享內存
24、構成Win32 API 函數的三個動態鏈接庫是什麽?
內核庫,用戶界面管理庫,圖形設備界面庫。
25、windows消息分為幾類?並對各類做簡單描述。
1.窗口消息:與窗口相關的消息,除WM_COMMAND之外的所有以WM_開頭的消息;
2.命令消息;用於處理用戶請求,以WM_COMMAND表示的消息;
3.控件通知消息:統一由WM_NOTIFY表示,
4.用戶自定義消息。(WM_USER 、 WM_APP)
26、MFC中,大部分類是從哪個類繼承而來?
CObject
27、TCP/IP 建立連接的過程
在TCP/IP協議中,TCP協議提供可靠的連接服務,采用三次握手建立一個連接。
第一次握手:建立連接時,客戶端發送連接請求到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到客戶端連接請求,向客戶端發送允許連接應答,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的允許連接應答,向服務器發送確認,客戶端和服務器進入通信狀態,完成三次握手
28、memset ,memcpy 的區別
memset用來對一段內存空間全部設置為某個字符,一般用在對定義的字符串進行初始化為‘\0‘。
memcpy用來做內存拷貝,你可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度。
29、已知strcpy函數的原型是: char * strcpy(char * strDest,const char * strSrc);不調用庫函數,實現strcpy函數。
char *strcpy(char *strDest, const char *strSrc)
{
if (strDest == NULL || strSrc == NULL)
return NULL;
if (strDest == strSrc)
return strSrc;
char *tempPtr = strDest;
while ((*strDest = *strSrc) != ‘\0‘);
return tempPtr;
}
30、已知類String 的原型為:
class String
{
public:
String(const char *str = NULL); // 普通構造函數
String(const String &other); // 拷貝構造函數
~ String(void); // 析構函數
String & operate =(const String &other); // 賦值函數
private:
char *m_data; // 用於保存字符串
};
String (const char *str = NULL)
{
if (str == NULL) { //strlen在參數為NULL時會拋異常才會有這步判斷
m_data = new char[1];
m_data[0] = ‘‘;
} else {
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
}
String (const String & other)
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
}
String & String::operator =(const String & other)
{
if (this = &other)
return *this;
delete []m_data;
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, othe.m_data);
return *this;
}
String::~ String(void)
{
delete []m_data ;
}
C/C++ 面試題記錄