首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 基礎進階:數組、字符串與 std::string 核心機制詳解

     編輯:關於C++

復合類型是構建複雜數據結構的基石。本文深入剖析 C++ 中數組與字符串的底層機制、常見陷阱,並重點對比 C 風格字符串與 std::string 的異同,幫助你寫出更安全、高效的代碼。

一、 數組:固定大小、連續內存的原生容器

1. 聲明與初始化規則

  • 大小必須為常量表達式(編譯期確定),不可用變量:int n = 10; int arr[n]; // 錯誤 (C++ 標準),需用 constexpr 或宏。
  • 未顯式初始化的局部數組元素值不確定(垃圾值),全局/靜態數組自動零初始化。
  • 初始化列表元素個數少於數組大小,剩餘元素值初始化(內置類型為 0)。
int scores[5] = {90, 85}; // {90, 85, 0, 0, 0}
char name[] = "Hello";    // 自動推導大小 6 (含 '\0')

2. 下標越界:未定義行為的溫床

C++ 不進行邊界檢查。arr[100] = 0; 不會編譯報錯,但可能破壞棧內存、導致難以復現的崩潰。務必確保下標在 [0, size-1] 範圍內。

3. 數組的「假象」:退化為指針

數組名在多數表達式中隱式轉換為指向首元素的指針(退化),失去大小信息。因此:

  • 不可賦值:int a[5], b[5]; a = b; // 錯誤
  • 不可比較:比較的是首地址而非內容。
  • 傳遞給函數實際傳的是指針,函數內 sizeof(arr) 返回指針大小而非數組大小。

對策:傳遞數組時同時傳遞大小,或改用 std::array/std::vector/std::span (C++20)。

二、 C 風格字符串:以 '\0' 為界的字符數組

1. 本質與結尾標誌

本質是 char[],必須以空字符 '\0' (ASCII 0) 結尾。標準庫函數 (strlen, strcpy, strcat, cout) 均依賴 '\0' 判定結束。

char a[10] = {'H', 'i'};      // 非字符串,無 '\0'
char b[10] = "Hi";            // 字符串,自動補 '\0' -> {'H','i','\0',0...}
char c[] = "Hi";              // 大小 3

2. sizeof vs strlen 易混淆點

  • sizeof(arr):整個數組佔用的字節數(包含未使用空間與 '\0')。
  • strlen(str):字符串實際長度(遇 '\0' 停止,不含 '\0')。
char s[20] = "Hello";
sizeof(s);   // 20
strlen(s);   // 5

3. 輸入陷阱與安全讀取

方法行為風險
cin >> arr讀單詞(遇空白停止),自動加 '\0'① 丟失空白 ② 易溢出(無長度限制)
cin.getline(arr, n)讀整行(含空白),遇 '\n' 停止,丟棄 '\n',加 '\0'最多讀 n-1 字符,安全
cin.get(arr, n)讀整行,保留 '\n' 在緩衝區連續調用需手動清理 '\n' (cin.get() 或 .ignore())

最佳實踐:優先使用 cin.getline(arr, size) 讀取整行;混合 >> 與 getline 時,先用 cin.ignore() 清理殘留換行符。

三、 std::string:現代 C++ 字符串的正確打開方式

1. 核心優勢

  • 動態內存管理:自動擴容,無緩衝區溢出風險。
  • 值語義:支援直接賦值 (s1 = s2)、拼接 (s1 + s2, s1 += s2)、比較 (==, <)。
  • 豐富介面:size(), length(), empty(), clear(), substr(), find(), c_str() 等。
  • 兼容 C API:c_str() 返回以 '\0' 結尾的 const char*。

2. 常用操作示例

std::string s1, s2 = "panther";
s1 = s2;                 // 賦值
std::string s3 = s1 + s2; // 拼接
s1 += "!";               // 追加
std::cout << s1.size();  // 長度 (無參數)
std::getline(cin, s1);   // 安全讀取整行 (含空白)

3. 與 C 字符串互轉

// C -> C++
char cstr[] = "Hello";
std::string cpp_str(cstr); // 或 cpp_str = cstr;

// C++ -> C
const char* p = cpp_str.c_str(); // 指針生命週期綁定 cpp_str
// 注意:不可對 c_str() 返回值修改,cpp_str 修改/銷毀會導致指針失效

四、 總結與建議

  1. 默認選擇 std::string 和 std::vector/array,避免手動內存管理與邊界錯誤。
  2. 必須接觸 C API 或極度敏感性能場景時,才考慮 C 風格數組/字符串,並嚴格控制大小與邊界。
  3. 理解數組退化為指針、'\0' 結尾約定、sizeof/strlen 差異 是避開經典坑的關鍵。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved