C++ 筆試題旨在短時間內檢測候選人對**語言核心機制、底層運作、現代最佳實踐**的掌握深度。本文精選高頻考題:位運算計數、引用與指標差異、const 引用語意、函式參數傳遞策略,附帶標準答案、評分細則、常見錯誤與延伸思考。
int countOnes(int x) {
int count = 0;
while (x) {
count++;
x = x & (x - 1);
}
return count;
}
// 輸入 x = 9999,輸出?
原理: x & (x - 1) 能**清除 x 最低位的 1**。迴圈執行次數即 1 的個數 (Brian Kernighan 演算法),時間複雜度 O(1 的個數) 優於 O(位寬)。
驗證: 999910 = 100111000011112,共 8 個 1。
#include // C++20
int count = std::popcount(static_cast(x)); // 硬體指令 POPCNT,單指令完成
// 或編譯器內建
int count = __builtin_popcount(x); // GCC/Clang/MSVC 支援
using Ref = int&; 別名合法)。
int a = 10;
int& ref = a; // 正確:初始化綁定 a
// int& ref2; // 錯誤:未初始化
// int& ref3 = 10; // 錯誤:非常數引用不能綁定暫時物件
const int& cref = 10; // 正確:const 引用延長暫時物件壽命
ref = 20; // a 變為 20
int b = 30;
ref = b; // 賦值操作:a = 30,而非 ref 綁定 b!
// int& ref4 = ref; // 合法:ref4 也綁定 a (引用的引用透過 typedef/using 間接實現)
| 特點 | 說明 | 對比:值傳遞 / 指標傳遞 |
|---|---|---|
| 1. 零副本、直接操作實參 | 記憶體中不產生實參副本,直接讀寫原物件。大型物件傳遞極高效。 | 值傳遞:複製構造、析構開銷大。指標:需解參考、可為 null。 |
| 2. 語法簡潔、無解參考雜訊 | 函式內像操作區域變數一樣操作實參,*ptr、ptr-> 雜訊全無。 | 指標:頻繁 */->,易寫錯、難閱讀。 |
| 3. 呼叫端無需取址 | 呼叫 func(obj) 而非 func(&obj),介面更乾淨。 | 指標:呼叫端必須 &,洩露「可修改」意圖。 |
對於小型型別 (int, double, 指標大小),**值傳遞通常比引用更快** (寄存器傳遞、無間接存取)。引用優勢在於**大型物件、不可複製型別、需修改實參、多型基類參數**。
當**同時滿足**以下條件:
void printString(const std::string& s) { // 接受 lvalue、rvalue、字面常量
std::cout << s << '\n';
}
std::string foo() { return "temp"; }
printString("hello world"); // 字面常量 → 暫時 std::string → 綁定 const&
printString(foo()); // 函式返回右值 → 綁定 const&
printString(std::string("temp")); // 顯式暫時物件 → 綁定 const&
// 非 const 引用無法綁定以上三者 → 編譯錯誤
// void bad(std::string& s); bad("hello"); // Error
// 1. 需修改實參 → 非 const 左值引用 (T&)
// 2. 不修改、型別小 (≤ 2*sizeof(void*)) 且可複製 → 值傳遞 (T)
// 3. 不修改、型別大或不可複製 → const 左值引用 (const T&)
// 4. 需轉移所有權 (C++11) → 右值引用 (T&&) 或 by-value + std::move
// 5. 萬能轉發模板 → 轉發引用 (T&&) + std::forward
int& bad() {
int x = 10;
return x; // 錯誤:返回區域變數引用 → 懸空引用
}
int& good() {
static int x = 10; // 靜態儲存期
return x; // 正確
}
int a = 1, b = 2;
(int&) (true ? a : b) = 10; // C++ 允許條件運算子返回左值引用
// a 變為 10
const std::string& ref = std::string("temp"); // 暫時物件壽命延長至 ref 作用域結束
// 但:
const std::string& ref2 = foo(); // foo() 返回值 (右值) 同樣延長
// 然而:
const std::string& ref3 = getStringRef(); // 若 foo 返回 const std::string&,不延長!
auto, nullptr, constexpr, std::move, std::forward, string_view, span, optional, variant、概念約束。C++ 筆試題看似考語法細節,實考**語言設計哲學內化程度**。《Effective C++》條款 1-3 (視 C++ 為語言聯邦、優先用 const/reference、理解物件生命週期) 是所有筆試題的底層邏輯。精準掌握「位運算技巧、引用/指標/值傳遞三選一決策、const 正確性、暫時物件壽命延長、RAII 資源管理」,並能手寫無誤的工業級程式碼片段,即可在筆試中脫穎而出。