理解std::vector::erase() 中的迭代器失效
在本次討論中,我們深入研究迭代器失效的主題:呼叫std::vector::erase()。從先前的爭論中可知,從向量中刪除元素會使位於被刪除元素之後的迭代器無效。然而,出現了一個問題:位於被擦除元素處的迭代器是否仍然被認為有效?
儘管我們直觀地理解位於被擦除位置的迭代器應該保持可用,但精確的行為並不總是清晰的。為了說明這個概念,讓我們分析以下從向量中刪除所有奇數整數的程式碼片段:
<code class="cpp">typedef std::vector<int> vectype; vectype vec; for (int i = 0; i < 100; ++i) vec.push_back(i); vectype::iterator it = vec.begin(); while (it != vec.end()) { if (*it % 2 == 1) vec.erase(it); else ++it; }</code>
雖然此程式碼成功執行,但它違反了最佳實踐。根據 C 標準,erase() 會使作為參數提供的迭代器或之後的所有迭代器無效。在這種情況下,這意味著被擦除位置的迭代器變得無效。
但是,erase() 可以方便地傳回一個新的迭代器,該迭代器指向緊接著被擦除元素之後的元素,或指向 vec.end () 如果不存在這樣的元素。這個新的迭代器可以用來安全地恢復迭代。
要注意的是,上述刪除奇數元素的方法效率不高。每次刪除一個元素時,後續元素都必須在向量中向左移動,導致複雜度為 O(n2)。使用擦除-刪除慣用法可以更有效地完成此任務,該慣用法的運行時間為 O(n)。透過建立像 is_odd() 這樣的謂詞,我們可以最佳化擦除操作:
<code class="cpp">bool is_odd(int x) { return (x % 2) == 1; } vec.erase(std::remove_if(vec.begin(), vec.end(), is_odd), vec.end());</code>
以上是## std::vector::erase() 中擦除位置處的迭代器仍然有效嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!