精選自資深面試題庫,覆蓋對象模型、類型轉換、模板、STL、內存管理、未定義行為等 C++ 核心硬骨頭。適合面試準備、自我檢測、技術深度鞏固。
char str1[] = "abc", str2[] = "abc"; const char str3[] = "abc", str4[] = "abc"; const char* str5 = "abc", *str6 = "abc"; cout << (str1==str2) << (str3==str4) << (str5==str6); // false false true
解析:
str1/str2 各自分配棧空間,地址不同const 數組同理,const 只影響可修改性str5/str6 指向靜態存儲區同一字符串常量 "abc" (編譯器合併優化),地址相同void UpperCase(char str[]) {
for (size_t i=0; i
鐵律:函數參數 char str[] 退化為 char*,sizeof 失效。需額外傳長度或用 std::string/std::span。
3. 隱式類型轉換的四種途徑
非內建類型 B → A 隱式轉換發生於:
class B : public A (公有繼承,含間接)
class B { operator A(); } (轉換函數)
class A { A(const B&); } (非 explicit 建構函數)
A& operator=(const A&) (賦值操作,廣義轉換)
4. 默認建構函數聲明陷阱
Test b(); // 錯誤!這是函數聲明,非對象構造
Test b; // 正確:調用默認建構函數
「最令人惱火的解析」:任何能被解析為聲明的語句,就會被解析為聲明。
5. 三元運算符類型一致性要求
cout << (true ? 1 : "1"); // 編譯錯誤:int 與 const char* 類型不兼容
?: 要求第二、三操作數類型相同,或可隱式轉換至公共類型。
6. 編譯期常量與 VLA 區別
unsigned int const size1 = 2; char str1[size1]; // OK: 編譯期常量
unsigned int const size2 = temp; char str2[size2]; // 錯誤: size2 非編譯期常量 (C99 VLA 除外,C++ 不支持)
C++ 要求陣列大小為編譯期常量表達式。
7. 無符號類型反向遍歷陷阱
for (vector::size_type i=v.size()-1; i>=0; --i) // 死循環!
// size_type 為 unsigned,i>=0 永真,i-- 從 0 變最大值
修正:for (auto i = v.size(); i-- > 0; ) 或 for (int i = v.size()-1; i >= 0; --i)。
8. 建構函數委托誤區 (C++11 前)
CLS() { CLS(0); } // 錯誤!創建臨時對象,不初始化 this
// 正確 (C++11): CLS() : CLS(0) {}
// 正確 (舊標準): CLS() { m_i = 0; } 或用 init 函數
函數體內調用建構函數只是創建臨時對象,不進行成員初始化。
9. 空類編譯器自動生成的 6 大成員函數
class Empty {
public:
Empty(); // 默認建構函數
Empty(const Empty&); // 拷貝建構函數
~Empty(); // 解構函數
Empty& operator=(const Empty&); // 拷貝賦值
Empty* operator&(); // 取址
const Empty* operator&() const; // const 取址
};
10. 強制轉換 vs 重新解釋轉換
float a = 1.0f;
(int)a; // 值轉換:構造新 int,值為 1
(int&)a; // 重新解釋:將 a 的 4 字節按 int 讀取,值為 1065353216 (IEEE 754 0x3F800000)
(float b = 0.0f; (int)b == (int&)b) // true:0.0 和 0 位模式全 0
展示值語義與位模式語義的本質差異。
11. vector 迭代器失效與 erase 陷阱
for (auto it = v.begin(); it != v.end(); ++it)
if (*it == 2) v.erase(it); // 錯誤:erase 導致後續元素前移,it 失效,漏檢
修正:it = v.erase(it) (C++11 返回下一有效迭代器) 或 if (*it == 2) { it = v.erase(it); } else { ++it; }。
12. memcpy 實現與記憶體重疊處理
void* mymemcpy(void* dest, const void* src, size_t n) {
char* d = (char*)dest;
const char* s = (const char*)src;
if (d > s && d < s + n) // 重疊且 dest 在 src 後:逆向拷貝
for (size_t i = n; i-- > 0; ) d[i] = s[i];
else // 正向拷貝
for (size_t i = 0; i < n; ++i) d[i] = s[i];
return dest;
}
標準 memcpy 行為未定義於重疊區域,memmove 保證正確處理重疊。面試常考察此邊界條件意識。