自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C++中vector迭代器哪些情況下會失效?

開發(fā) 前端
為了避免由于迭代器失效引起的錯誤,我們在使用迭代器遍歷vector時,要避免在可能使迭代器失效的操作前后更新迭代器,或者盡量減少對vector的修改操作直到遍歷完成。

在C++編程中,std::vector是一個非常強大的容器,用于存儲動態(tài)數(shù)組。然而,使用std::vector時需要注意的一個重要方面是其迭代器的行為。當vector的容量發(fā)生變化時(例如添加或刪除元素),迭代器可能會失效,這可能導(dǎo)致程序錯誤。

迭代器失效的情況:

1、重新分配內(nèi)存

當向vector添加新元素導(dǎo)致其容量不足時,vector會自動擴展以容納更多的元素。這種情況下,所有指向舊內(nèi)存區(qū)域的迭代器、指針和引用都會失效。

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3};
    auto it = vec.begin(); // 指向第一個元素


    // 添加一個元素可能觸發(fā)重新分配
    vec.push_back(4);


    if (it != vec.end()) {
        std::cout << "Element: " << *it << std::endl;
    } else {
        std::cout << "Iterator is invalid." << std::endl;
    }


    return 0;
}

在這個例子中,如果push_back()操作觸發(fā)了重新分配,則it迭代器將變得無效,嘗試訪問它會導(dǎo)致未定義行為。

2、刪除元素

從vector中移除元素后,該位置之后的所有元素及其對應(yīng)的迭代器都會受到影響。

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.erase(vec.begin()); // 刪除第一個元素


    while (it != vec.end()) {
        std::cout << *it << " ";
        ++it;
    }
    std::cout << std::endl;


    return 0;
}

這里,erase()返回的是下一個有效元素的迭代器,確保了循環(huán)的安全性。

3、使用 clear() 方法清空容器

當調(diào)用clear()時,所有元素都會被刪除,但已分配的內(nèi)存空間不會被釋放。這意味著容器的容量保持不變,但所有指向原元素的迭代器、指針或引用都將變得無效。

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.begin(); // 獲取開始位置的迭代器


    std::cout << "Before clear: Capacity = " << vec.capacity() << ", Size = " << vec.size() << std::endl;


    vec.clear(); // 清空向量


    std::cout << "After clear: Capacity = " << vec.capacity() << ", Size = " << vec.size() << std::endl;


    if (it != vec.end()) {
        // 這里會輸出錯誤信息,因為it已經(jīng)失效
        std::cout << "Element: " << *it << std::endl;
    } else {
        std::cout << "Iterator is invalid after calling clear()." << std::endl;
    }


    return 0;
}

調(diào)用clear()后,迭代器it仍然指向原來的內(nèi)存位置,但由于這些位置上的元素已被刪除,所以it實際上是無效的。為了安全起見,應(yīng)該在clear()之后重新獲取迭代器。

4、使用 resize() 改變大小

減小尺寸:如果通過resize()減小vector的尺寸,那么超出新尺寸范圍的元素會被刪除,相應(yīng)的迭代器也會失效。

增大尺寸:如果增加尺寸,則新增加的位置上的迭代器是未定義的(直到它們被初始化)。

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.begin() + 2; // 指向第三個元素


    std::cout << "Before resize: Capacity = " << vec.capacity() << ", Size = " << vec.size() << std::endl;
    std::cout << "Element at it before resize: " << *it << std::endl;


    vec.resize(2); // 減小尺寸到2


    std::cout << "After resizing to 2: Capacity = " << vec.capacity() << ", Size = " << vec.size() << std::endl;
    if (it != vec.end()) {
        // 這里可能會導(dǎo)致未定義行為,因為it已經(jīng)失效
        std::cout << "Element at it after resize: " << *it << std::endl;
    } else {
        std::cout << "Iterator is invalid after resizing to 2." << std::endl;
    }


    vec.resize(6, 0); // 增大尺寸到6,并用0填充
    it = vec.begin() + 2; // 重新獲取有效迭代器


    std::cout << "After resizing to 6: Capacity = " << vec.capacity() << ", Size = " << vec.size() << std::endl;
    std::cout << "Element at it after resizing to 6: " << *it << std::endl;


    return 0;
}

5、使用 swap() 交換兩個 vector 的內(nèi)容

當兩個vector之間進行數(shù)據(jù)交換時,它們各自的迭代器、指針和引用都將指向?qū)Ψ降臄?shù)據(jù)結(jié)構(gòu)。這意味著原來的迭代器將不再指向原來的數(shù)據(jù)。

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = {4, 5, 6};


    auto it1 = vec1.begin();
    auto it2 = vec2.begin();


    std::cout << "Before swap: vec1[0] = " << *it1 << ", vec2[0] = " << *it2 << std::endl;


    vec1.swap(vec2); // 交換兩個向量的內(nèi)容


    std::cout << "After swap: vec1[0] = " << *it1 << ", vec2[0] = " << *it2 << std::endl;


    // 輸出顯示迭代器現(xiàn)在指向了交換后的數(shù)據(jù)
    std::cout << "it1 now points to: " << *it1 << std::endl;
    std::cout << "it2 now points to: " << *it2 << std::endl;


    return 0;
}

6、使用 assign() 重新賦值

assign()可以用來替換vector中的所有元素,這個過程類似于先調(diào)用clear()再插入新元素。因此,任何之前存在的迭代器都會失效。

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.begin();


    std::cout << "Before assign: Element at it = " << *it << std::endl;


    vec.assign(3, 0); // 用3個0替換原有元素


    if (it != vec.end()) {
        // 這里會導(dǎo)致未定義行為,因為it已經(jīng)失效
        std::cout << "After assign: Element at it = " << *it << std::endl;
    } else {
        std::cout << "Iterator is invalid after assign." << std::endl;
    }


    // 重新獲取有效的迭代器
    it = vec.begin();
    std::cout << "New element at it: " << *it << std::endl;


    return 0;
}

vector刪除經(jīng)典錯誤

當從vector中刪除一個元素時,所有指向該元素及其之后元素的迭代器都會失效。如果繼續(xù)使用這些迭代器,會導(dǎo)致未定義行為。

下面這個是新手最容易犯的一個錯誤:

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};


    for (auto it = vec.begin(); it != vec.end(); ++it) {
        if (*it == 3) {
            vec.erase(it); // 刪除元素3
        }
        std::cout << *it << " "; // 繼續(xù)使用失效的迭代器
    }
    std::cout << std::endl;


    return 0;
}

當*it == 3時,調(diào)用vec.erase(it)會刪除元素3。

erase()返回的是下一個有效元素的迭代器,但在這個例子中,it并沒有更新為新的迭代器,而是繼續(xù)遞增,導(dǎo)致訪問已失效的迭代器。

正確的做法是:

#include <iostream>
#include <vector>


int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};


    for (auto it = vec.begin(); it != vec.end(); ) {
        if (*it == 3) {
            it = vec.erase(it); // 更新迭代器
        } else {
            ++it; // 只有在沒有刪除元素的情況下才遞增迭代器
        }
    }


    for (const auto &val : vec) {
        std::cout << val << " ";
    }
    std::cout << std::endl;


    return 0;
}

總結(jié):

為了避免由于迭代器失效引起的錯誤,我們在使用迭代器遍歷vector時,要避免在可能使迭代器失效的操作前后更新迭代器,或者盡量減少對vector的修改操作直到遍歷完成。此外,使用基于范圍的for循環(huán)(如for (auto &elem : vec))可以避免直接管理迭代器,從而簡化代碼并減少出錯的機會。

責(zé)任編輯:武曉燕 來源: CppPlayer
相關(guān)推薦

2021-04-15 08:01:27

Spring聲明式事務(wù)

2015-06-01 06:39:18

JavaJava比C++

2015-06-29 14:23:13

JavaC++慢很多

2025-04-29 08:30:00

迭代器失效C++編程

2024-08-01 08:29:45

Spring參數(shù)類型

2010-02-04 15:51:07

C++迭代器

2010-02-06 16:05:51

C++ Vector

2010-01-28 14:11:43

C++迭代器

2021-12-13 11:12:41

Spring事務(wù)失效

2024-12-01 18:29:42

2021-11-08 15:17:15

變量Defer 失效

2023-11-23 23:52:06

options請求瀏覽器

2021-06-04 09:17:13

JavaScriptBoolean函數(shù)

2022-06-27 07:23:44

MySQL常量優(yōu)化

2009-12-01 11:39:39

配置路由器IP

2022-09-14 19:50:22

事務(wù)場景流程

2013-09-12 10:41:39

VDI部署

2009-12-09 10:41:26

配置靜態(tài)路由

2023-03-27 13:00:13

Javascript前端

2010-04-14 17:46:10

Oracle數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號