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

PHP 源碼閱讀:array_slice 與 array_splice 實現差異與效能考量

     編輯:PHP 相關知識

PHP 源碼閱讀:array_slice 與 array_splice 實現差異與效能考量

array_slice(取出切片)與 array_splice(移除並可替換切片)是 PHP 陣列操作核心函式,底層均在 ext/standard/array.c 實現。本文解析參數處理、指標移動、記憶體分配、返回值最佳化等關鍵邏輯。

函式簽名

array_slice(array $array, int $offset, int $length = null, bool $preserve_keys = false): array
array_splice(array &$array, int $offset, int $length = null, mixed $replacement = []): array

參數處理邏輯(兩者共通)

  1. offset 正規化:
    • offset >= 0 直接使用;offset > n 視為 n(返回空)。
    • offset < 0 轉為 n + offset;若結果 < 0 則歸零。
  2. length 正規化:
    • length < 0 轉為 n - offset + length(從末尾倒數)。
    • 若 offset + length > n 則截為 n - offset。
    • 最終 length < 0 直接返回空。

array_slice 核心流程

  1. 正規化參數。
  2. 將內部陣列指標移至 offset 位置。
  3. 拷貝 length 個元素至新陣列(preserve_keys=true 保留原數字鍵,否則重新索引 0...)。
  4. 返回新陣列,**不修改原陣列**。

array_splice 核心流程

  1. 正規化參數(同 array_slice)。
  2. 僅當返回值被使用時 才分配返回陣列(源碼檢查 return_value_used),避免無用記憶體分配。
  3. 從原陣列移除 offset 起 length 個元素。
  4. 若提供 $replacement,將其元素插入移除位置。
  5. 返回被移除元素組成的陣列(若有使用返回值)。

源碼關鍵片段:返回值按需分配

if (return_value_used) {
    int size = length;
    // ... 計算實際 size ...
    array_init_size(return_value, size > 0 ? size : 0);
    rem_hash = &Z_ARRVAL_P(return_value);
}

這是 C 層級的「惰性求值」優化:$removed = array_splice(...) 才建立返回陣列;單純 array_splice(...) 不產生返回值開銷。

使用範例對比

$arr = ['a','b','c','d','e'];
print_r(array_slice($arr, 2, -1));      // ['c','d'] 保留鍵 0,1
print_r(array_slice($arr, 2, -1, true)); // ['c','d'] 保留原鍵 2,3

$arr = ['red','green','blue','yellow'];
array_splice($arr, 2);           // $arr=['red','green']  返回 ['blue','yellow']
array_splice($arr, 1, -1);       // $arr=['red','yellow'] 返回 ['green','blue']
array_splice($arr, 1, count($arr), 'orange'); // $arr=['red','orange']
array_splice($arr, -1, 1, ['black','maroon']); // 替換最後一元素
array_splice($arr, 3, 0, 'purple'); // 在索引 3 插入,不移除

效能與最佳實踐

  • 大陣列切片:array_slice 複製資料,記憶體翻倍;若只需迭代部分區間,考慮 ArrayIterator + LimitIterator 零拷貝。
  • 頻繁插入/刪除:陣列非連結列表,中間操作 O(n);高頻場景改用 SplDoublyLinkedList。
  • 保留鍵名:preserve_keys=true 適用關聯陣列;索引陣列預設重建索引更符合直覺。

總結

理解參數正規化規則、preserve_keys 行為差異、array_splice 的副作用(修改原陣列)與返回值按需分配優化,能寫出更健壯、高效的陣列操作代碼。

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