經典面試題:「不使用 for/while 迴圈,不使用遞迴,如何計算 1 到 100 的和?」甚至延伸為任意區間 [min, max] 求和。常規解法(高斯公式 n*(n+1)/2)雖然 O(1) 但屬於數學技巧,而非程式設計技巧。本文介紹一種利用 C++ 物件建構/解構機制 + 靜態成員 的「側寫」解法,展現語言特性的創造性運用。
N、SUM 隸屬於類別而非物件,全域唯一,生命週期贯穿整個程式。N++、SUM += N。new ClassName[size] 會連續呼叫 size 次建構函數,再呼叫 size 次解構函數。max - min + 1 控制建構次數,並先將靜態計數器 N 重置為 min - 1,即可累加 min ~ max。#include <iostream>
using namespace std;
class Accumulator {
public:
Accumulator(); // 建構函數
static int getSum(); // 取得累加結果
private:
static int N; // 當前計數
static int SUM; // 累加和
};
// 靜態成員定義與初始化(必須在類別外部)
int Accumulator::N = 0;
int Accumulator::SUM = 0;
Accumulator::Accumulator() {
N++;
SUM += N;
}
int Accumulator::getSum() {
return SUM;
}
int main() {
int min, max;
cout << "請輸入求和區間 [min, max] (min > 0, max >= min):\n";
cout << "min: "; cin >> min;
while (min <= 0) { cout << "min 必須 > 0,重新輸入: "; cin >> min; }
cout << "max: "; cin >> max;
while (max < min) { cout << "max 必須 >= min,重新輸入: "; cin >> max; }
Accumulator::N = min - 1; // 關鍵:重置計數起點
Accumulator *arr = new Accumulator[max - min + 1]; // 觸發 N 次建構
cout << min << " ~ " << max << " 的和 = " << arr->getSum() << endl;
delete[] arr; // 釋放記憶體(觸發解構,但不影響 SUM)
return 0;
}
new Accumulator[k] 在堆疊上分配 k 個物件,編譯器生成程式碼迴圈呼叫 k 次建構函數——這把「迴圈」隱藏在編譯器生成的程式碼中,符合「原始碼中無迴圈/遞迴」的限制。SUM 累加過程不依賴物件實例,故 delete[] 後數值保留。同樣原理,vector 也會觸發建構函數,語法更現代、記憶體管理更安全。
accumulate、iota + reduce (C++17) 內部含迴圈,但原始碼單行。此技巧屬於「語言律師」層面的展示,不建議用於生產環境(可讀性差、效能不可預期、濫用建構/解構副作用)。但它極佳地展示了:
面試中若遇到此類題目,先給出高斯公式 O(1) 正解,再補充此技巧作為「額外展示語言深度」,效果最佳。