首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C/C++ 內存管理:new 動態分配與 strcpy 與指針賦值的本質區別

     編輯:程式設計綜合問答

前言

C/C++ 初學者常遇到這樣的困惑:char *p = new char[20]; 分配內存後,為什麼 strcpy(p, "helloworld") 正常,而 p = "helloworld" 會導致警告甚至運行時錯誤?本文將從內存模型、指針本質、字符串字面量存儲三個維度徹底講透這個問題。

核心代碼對比

char *p = new char[20];      // 1. 堆上分配 20 字節,p 指向首地址
strcpy(p, "helloworld");     // 2. 將字面量內容「拷貝」到 p 指向的內存
// 對比
p = "helloworld";            // 3. 讓 p 直接指向字面量所在的只讀區

內存佈局圖解

+------------------+       +------------------+
|  Stack (棧)      |       |  Heap (堆)       |
|  p (指針變量) ───┼──────▶│  20 bytes 空間   |  ← new char[20]
+------------------+       +------------------+

+------------------+       +------------------+
|  Stack           |       |  .rodata (只讀區) |
|  p (指針變量) ───┼──────▶│  "helloworld\0"  |  ← 字符串字面量
+------------------+       +------------------+

深度解析兩種賦值方式

方式一:strcpy(p, "helloworld") —— 內容拷貝

  • 操作對象:p 指向的堆內存(可讀寫)。
  • 行為:將字面量 "helloworld" 的每個字符(含結束符 \0)逐個複製到堆內存。
  • 結果:p 仍指向堆內存,內容可修改,如 p[0] = 'H'; 合法。
  • 責任:必須配對 delete[] p; 釋放堆內存,否則洩漏。

方式二:p = "helloworld" —— 指針重綁定

  • 操作對象:指針變量 p 本身(棧上)。
  • 行為:丟棄原本指向的堆內存地址,改指向只讀數據段的字面量地址。
  • 後果:
    1. 內存洩漏:原 new char[20] 分配的 20 字節堆內存無指針引用,無法釋放。
    2. 非法修改風險:字面量存放在只讀區,嘗試 p[0] = 'H'; 會導致段錯誤/訪問違例。
    3. 編譯器警告:將 const char* 隱式轉換為 char*,丟棄 const 資格。

為什麼 VS 只給警告不報錯?

C++ 標準允許字符串字面量隱式轉換為 char*(為兼容 C 舊代碼),但強烈建議使用 const char* 接收字面量:

const char *p = "helloworld"; // 正確:編譯器強制只讀
// p[0] = 'H'; // 編譯錯誤,保護只讀區

最佳實踐總結

場景推薦做法關鍵點
需要可修改的字符串緩衝區std::string s = "helloworld"; 或 std::vector<char>自動管理內存,避免手動 new/delete
必須用 C 風格 char* 且需修改char *p = new char[len]; strcpy(p, src); ... delete[] p;配對 new[]/delete[],檢查邊界
只讀字符串常量const char *p = "literal";編譯期保護,零拷貝開銷
C++17 起std::string_view sv = "literal";非擁有式視圖,極低開銷

延伸:現代 C++ 替代方案

除非維護舊代碼或編寫底層庫,優先使用 std::string、std::string_view、std::vector,利用 RAII 自動管理生命週期,從根源消除指針算術、內存洩漏、野指針等經典問題。

結語

strcpy 是「搬運內容」,p = "..." 是「換掉地址」。理解指針變量本身 vs 指向的內存、堆 vs 只讀區、所有權語義,是從 C/C++ 初學者進階為系統級工程師的必經之路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved