整理全網c++1000道面試題。文章所展現為統計高頻題及答案。
需要1000道面試PDF,【「連結」】
1 strlen和sizeof區別?
strlen和sizeof是C++中用於處理字符串和計算內存大小的操作。
- strlen函數:
- strlen函數是C標準庫中的函數,用於計算字符串的長度,即字符串中字符的個數(不包括結尾的空字符'\0')。
- 它接受一個以'\0'結尾的字符數組作為參數,並返回該字符串的長度。
- strlen函數通過遍歷字符數組來計算長度,直到遇到空字符為止。
- sizeof運算符:
- sizeof是C++中的運算符,用於計算對象或類型的大小,即占用的內存字節數。
- 它可以用於計算各種類型的大小,包括基本類型、自定義類型和數組等。
- sizeof運算符在編譯時求值,返回的結果是一個常量表達式,在編譯階段就可以確定。
區別:
- strlen用於計算以'\0'結尾的字符數組的長度,即字符串的長度,返回的是字符個數。
- sizeof用於計算對象或類型的大小,返回的是占用的內存字節數。
需要注意的是,strlen計算的是字符串的實際長度,而sizeof計算的是類型或對象占用的內存大小。因此,在使用時要注意選擇適當的操作,以滿足具體的需求。
int main()
{
const char* str = "name"; 4
sizeof(str); // 取的是指針str的長度,是8
strlen(str); // 取的是這個字符串的長度,不包含結尾的 \0。大小是4
return 0;
}
2 C++ 中的異常處理方法
在程序執行過程中,由於程式設計師的疏忽或是系統資源緊張等因素都有可能導致異常,任何程序都無法保 證絕對的穩定,常見的異常有: 數組下標越界
除法計算時除數為0 動態分配空間時空間不足 ... 如果不及時對這些異常進行處理,程序多數情況下都會崩潰。
1.try、throw和catch關鍵字
代碼中,對兩個數進行除法計算,其中除數為0。可以看到以上三個關鍵字,程序的執行流程是先執行 try包裹的語句塊,如果執行過程中沒有異常發生,則不會進入任何catch包裹的語句塊,如果發生異 常,則使用throw進行異常拋出,再由catch進行捕獲,throw可以拋出各種數據類型的信息,代碼中使 用的是數字,也可以自定義異常class。catch**根據*throw*拋出的數據類型進行精確捕獲(不會出現類型 轉換),如果匹配不到就直接報錯,可以使用**catch(...)的方式捕獲任何異常(不推薦)。當然,如果catch了異常,當前函數如果不進行處理,或者已經處理了想通知上一層的調用者,可以在catch裡面再throw異常。
#include <iostream>
using namespace std;
int main() {
double m = 1, n = 0;
try {
cout << "before dividing." << endl;
if (n == 0)
throw - 1; // 拋出int型異常
else if (m == 0)
throw - 1.0; // 拋出double型異常
else
cout << m / n << endl;
cout << "after dividing." << endl;
}
catch (double d) {
cout << "catch (double)" << d << endl;
}
catch (...) {
cout << "catch (...)" << endl;
}
cout << "finished" << endl;
return 0;
}
2.函數的異常聲明列表
有時候,程式設計師在定義函數的時候知道函數可能發生的異常,可以在函數聲明和定義時,指出所能拋出 異常的列表,寫法如下:
int fun() throw(int,double,A,B,C){...};
這種寫法表名函數可能會拋出int,double型或者A、B、C三種類型的異常,如果throw中為空,表明不 會拋出任何異常,如果沒有throw則可能拋出任何異常
3.C++ 標準異常類
bad_typeid:使用typeid運算符,如果其操作數是一個多態類的指針,而該指針的值為 NULL,則會拋出此異常,例如:
#include <iostream>
#include <typeinfo>
using namespace std;
class A {
public:
virtual ~A();
};
int main() {
A* a = nullptr;
try {
cout << typeid(*a).name() << endl; // Error condition
} catch (bad_typeid) {
cout << "Object is NULL" << endl;
}
return 0;
}
bad_cast:在用 dynamic_cast 進行從多態基類對象(或引用)到派生類的引用的強制類型轉換時,如果轉換是不安全的,則會拋出此異常 bad_alloc:在用 new 運算符進行動態內存分配時,如果沒有足夠的內存,則會引發此異常
out_of_range:用 vector 或 string的at 成員函數根據下標訪問元素時,如果下標越界,則會拋出此異常
3 初始化和賦值的區別
初始化是在對象創建時進行的賦值,使用構造函數或拷貝構造函數;賦值是在對象已存在的情況下進行的重新賦值,使用賦值操作符函數。兩者的調用方式和對象狀態有所不同。
class A {
public:
int num1;
int num2;
public:
A(int a = 0, int b = 0) :num1(a), num2(b) {};
A(const A& a) {};
//重載 = 號操作符函數
A& operator=(const A& a) {
num1 = a.num1 + 1;
num2 = a.num2 + 1;
return *this
};
};
int main() {
A a(1, 1);
A a1 = a; //拷貝初始化操作,調用拷貝構造函數
A b;
b = a;//賦值操作,對象a中,num1 = 1,num2 = 1;對象b中,num1 = 2,num2 = 2
return 0;
}