6.5 陣列的初始化

宣告陣列時可以同時指定初值,避免後來訪問到未初始化的垃圾值。不同的初始化方式有不同的優缺點。

方式 1:使用大括號指定初值

int a[5] = {1, 2, 3, 4, 5};    // 完整初始化
int b[5] = {10, 20};            // 前兩個設 10、20,其餘自動設 0
int c[5] = {};                  // 所有元素設 0

方式 2:省略陣列大小

int a[] = {1, 2, 3};            // 編譯器自動推斷大小為 3

方式 3:全域陣列自動初始化為 0

int a[1000];  // 全域宣告,所有元素自動為 0

int main() {
    int b[1000];  // 局域宣告,所有元素為未知(垃圾值)
}

方式 4:使用迴圈初始化

int a[20];
for (int i = 0; i < 20; i++) {
    a[i] = i + 1;              // 先宣告,後初始化
}

排版小提醒:大括號初始化比照 1.5 的逗號慣例——逗號後加一個空格{1, 2, 3} ✓、{1,2,3} ✗。

範例程式碼

#include<iostream>
using namespace std;
int main() {
    // 方式 1:宣告時初始化部分元素
    int a[5] = {10, 20, 30};

    // a[0]=10, a[1]=20, a[2]=30, a[3]=0, a[4]=0
    for (int i = 0; i < 5; i++) {
        cout << "a[" << i << "]=" << a[i] << '\n';
    }

    cout << "---\n";

    // 方式 2:宣告時全部初始化為 0
    int b[5] = {};

    // b[0]~b[4] 都是 0
    for (int i = 0; i < 5; i++) {
        cout << "b[" << i << "]=" << b[i] << '\n';
    }

    return 0;
}

執行結果:

a[0]=10
a[1]=20
a[2]=30
a[3]=0
a[4]=0
---
b[0]=0
b[1]=0
b[2]=0
b[3]=0
b[4]=0

查表資料:把固定不變的資料寫進初始化

初始化還有一個漂亮的用法:把題目裡固定不變的「查表資料」直接寫進大括號。例如每個月的天數:

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// days[m] 就是 m 月的天數;days[0] 塞 0 佔位,讓「1 月」剛好住在 days[1]

有了這張表,「m 月有幾天」變成取一格 days[m]——原本要寫的 12if 全部消失。days[0] 佔位正是 6.3 的 1-base 對齊技巧。站上的還剩幾天呢?用的就是這招(注意:該題是 2024 閏年,2 月要填 29)。

初始化不是免費的

int a[1000000] = {}; 不是魔法——電腦要老老實實把一百萬格逐格清成 0。單獨做一次沒感覺,但放進多組測資的迴圈裡就出事了:

while (t--) {                  // 最多 10^5 組測資
    int a[1000000] = {};       // ✗ 每組都清一百萬格 → 總共 10^11 步,TLE
    // ...處理這組測資...
}

修法:把陣列搬到全域(程式開始時自動清 0,只做一次),每組結束後只清自己用過的格子

int a[1000000];                // 全域:自動全 0(只做一次)

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        // ...讀入並處理這組測資,只會動到 a[0] ~ a[n-1]...
        for (int i = 0; i < n; i++) a[i] = 0;   // 只清用過的前 n 格
    }
    return 0;
}

若題目保證「所有 n 的總和 \le 10^6」,整個程式的清理工作加起來也才 10^6 步——這種總和保證,就是在暗示你這樣做。本站曾用一道這類題目實測:整包重清的版本要跑 6.9 秒(時限 1 秒),改成只清用過的前 n 格之後 0.1 秒。

動手試試看:在上面「四種樣子」的程式碼中,把 int b[5] = {}; 改成 int b[5];(不初始化),執行看看。你會看到 b 陣列輸出垃圾值。想想看為什麼 a 陣列反而有明確的初值?