經典面試題:「不使用遞歸、不使用迴圈,求 1 到 100 的和」。常規思維陷入死胡同,實則可利用 C++ 物件生命週期機制 將「迴圈」轉嫁給編譯器生成的建構/解構函數呼叫序列。
new T[N] 會連續呼叫 N 次 T::T(),delete[] 連續呼叫 N 次 T::~T()。在建構函數中累加靜態計數器,即可完成求和。
#include
using namespace std;
class Accumulator {
public:
Accumulator() {
N++;
SUM += N;
}
static int getSum() { return SUM; }
static void reset(int start) { N = start - 1; SUM = 0; }
private:
static int N;
static int SUM;
};
int Accumulator::N = 0;
int Accumulator::SUM = 0;
int main() {
int min, max;
cout << "輸入區間最小值 (min > 0): "; cin >> min;
while (min <= 0) { cout << "非法,重新輸入: "; cin >> min; }
cout << "輸入區間最大值 (max >= min): "; cin >> max;
while (max < min) { cout << "非法,重新輸入: "; cin >> max; }
Accumulator::reset(min);
Accumulator* arr = new Accumulator[max - min + 1];
cout << min << "~" << max << " 的和為: " << arr->getSum() << endl;
delete[] arr;
return 0;
}
| 步驟 | 發生動作 | 靜態變數變化 |
|---|---|---|
1. reset(min) | 設定 N = min-1, SUM = 0 | 初始化基準值 |
2. new Accumulator[n] | 連續呼叫 n 次建構函數 | 每次 N++ 並 SUM += N |
| 3. 建構完成 | N 從 min 遞增至 max,SUM 累加完成 | SUM = Σ(min..max) |
4. getSum() | 直接返回結果 | 無副作用 |
5. delete[] | 呼叫 n 次解構函數 | 靜態成員不受影響 |
vector v(count); 同理觸發建構序列,自動管理記憶體。constexpr 遞歸/摺疊表達式更優雅,但本題限定「無遞歸」。| 優點 | 缺點/風險 |
|---|---|
| 零顯式迴圈/遞歸,思維反轉精彩 | 依賴建構函數副作用,違反「建構只初始化」原則 |
| 展示對 C++ 物件模型深度理解 | 大區間分配陣列記憶體,可能 bad_alloc |
| 代碼極短,適合競賽/面試展示 | 可讀性差,維護成本高,嚴禁用於生產代碼 |
int Accumulator::N = 0;),否則連結錯誤。new[]/delete[] 配對,否則記憶體洩漏。vector、unique_ptr 如何改進 RAII 安全性。constexpr、模板元編程、std::iota+accumulate 等現代寫法。此解法本質是將迴圈遷移至編譯器生成的建構序列,屬於「技巧型」而非「工程型」解法。它極佳地考察候選人對 C++ 物件生命週期、靜態儲存期、陣列新建/刪除語義的掌握度。實際專案中,請老誠實寫 for 或 std::accumulate——清晰、安全、零成本抽象。