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

Qt 學習之路 (36):容器類迭代器與隱式資料共享深度解析

     編輯:關於C語言

Qt 容器類 (QList、QVector、QLinkedList 等) 提供兩種迭代器風格:Java 風格 (易用) 與 STL 風格 (通用算法相容)。並透過隱式資料共享 (Copy-on-Write) 實現高效值傳遞語意。

Java 風格迭代器:位置在「元素之間」

迭代器不指向元素本身,而是指向「第一個元素之前」、「元素之間」、「最後一個元素之後」。

只讀迭代器 QListIterator<T>

QList<double> list;
// ... 填充資料
QListIterator<double> i(list);
while (i.hasNext()) {
    doSomethingWith(i.next());
}
// 反向遍歷
i.toBack();
while (i.hasPrevious()) {
    doSomethingWith(i.previous());
}

讀寫迭代器 QMutableListIterator<T>

支援遍歷過程中插入、刪除、修改:

QMutableListIterator<double> i(list);
while (i.hasNext()) {
    if (i.next() < 0.0)
        i.remove();  // 安全刪除當前元素
}

STL 風格迭代器:指標語意與 const 正確性

每個容器提供 iterator (可修改) 與 const_iterator (唯讀)。begin() 指向首元素,end() 指向尾後位置 (如長度 5 的容器,end() 相當於 list[5])。

典型遍歷模式

QList<double>::iterator i = list.begin();
while (i != list.end()) {
    *i = qAbs(*i);  // 解參考修改元素
    ++i;
}

⚠️ 臨時物件陷阱

若函式回傳容器值 (如 splitter->sizes()),必須先拷貝再迭代:

// 錯誤:每次迴圈重建臨時物件,迭代器失效
QList<int>::const_iterator i = splitter->sizes().begin();

// 正確:先拷貝
QList<int> list = splitter->sizes();
QList<int>::const_iterator i = list.begin();

Java 風格迭代器建構子內部自動處理拷貝,避免此問題。

隱式資料共享 (Copy-on-Write):值傳遞零負擔

Qt 容器與 QString、QImage、QPixmap 等類別採用引用計數機制:

  • 拷貝/傳值/回傳值:僅複製指標與增加引用計數,極度廉價
  • 寫入操作:偵測引用計數 > 1 時才深度複製資料 (分離)

最佳實踐:釋放隱式共享效能

  1. 唯讀存取用 at() 而非 []:[] 可作左值,編譯器無法判斷是否會修改,被迫分離;at() 唯讀,保證共享。
  2. 優先使用 const_iterator、constBegin()、constEnd():非 const 迭代器可能觸發分離。

值回傳風格範例

QVector<double> sineTable() {
    QVector<double> vect(360);
    for (int i = 0; i < 360; ++i)
        vect[i] = std::sin(i / (2 * M_PI));
    return vect;  // 高效回傳,無深度複製
}

QVector<double> v = sineTable();  // 自然寫法,效能無虞

對比 STL 需透過參考參數輸出的笨重風格,Qt 隱式共享讓 C++ 也能享有 Java/動態語言般直觀的值語意。

foreach 宏:語法糖與注意事項

QLinkedList<Movie> list;
Movie movie;
// ...
foreach (movie, list) {
    if (movie.title() == "Citizen Kane") {
        std::cout << "Found Citizen Kane" << std::endl;
        break;
    }
}
  • 實為宏展開,自動建立唯讀拷貝迭代
  • 迴圈變數必須在迴圈外宣告,特別是含逗號型別如 QPair<int, double> 時唯一合法寫法

總結

掌握兩種迭代器風格適用場景、避開 STL 迭代器臨時物件陷阱、善用 at()/const_iterator 釋放隱式共享效能,能寫出既優雅又高效的 Qt 容器操作程式碼。

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