簡體   English   中英

如何使用向量 <T> :: reverse_iterator具有一個元素

[英]how to use vector<T>::reverse_iterator with one element

我將poll()與std :: vector一起使用。 注冊的監聽套接字。

std::vector<struct pollfd> fds;
fds.push_back(server_sock);

並添加新的客戶端套接字或連接的客戶端會話可以執行某些操作。

// poll() ...
for(std::vector<struct pollfd>::reverse_iterator it = fds.rbegin(); it != fds.rend(); it++) {
    if (it->fd == server_sock) {
        struct pollfd newFd;
        newFd.fd = newClient;
        newFd.events = POLLIN;
        fds.push_back(newFd);
    } else {
        // do something.
    }
}

但是當存在1或2或4向量的元素時,reverse_iterator不能正常工作。 我不明白為什么要這么做。

隨附示例代碼。

typedef struct tt_a {
    int a;
    short b;
    short c;
} t_a;

vector<t_a> vec;
for (int i = 0; i < 1; i++) {
    t_a t;
    t.a = i;
    t.b = i;
    t.c = i;
    vec.push_back(t);
}

for(vector<t_a>::reverse_iterator it = vec.rbegin(); it != vec.rend(); it++) {
    if (it->a == 0) {
        t_a t;
        t.a = 13;
        t.b = 13;
        t.c = 13;
        vec.push_back(t);
    }

    printf("[&(*it):0x%08X][it->a:%d][&(*vec.rend()):0x%08X]\n",
            &(*it), it->a, &(*vec.rend()));
}

printf("---------------------------------------------\n");

for(vector<t_a>::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it) {
    if (it->a == 3) {
        it->a = 33;
        it->b = 33;
        it->c = 33;
    }
    printf("[&(*it):0x%08X][it->a:%d][&(*vec.rend()):0x%08X]\n",
            &(*it), it->a, &(*vec.rend()));
}

結果:

[&(*it):0x01ADC010][it->a:0][&(*vec.rend()):0x01ADC028]
[&(*it):0x01ADC008][it->a:33][&(*vec.rend()):0x01ADC028]
[&(*it):0x01ADC000][it->a:0][&(*vec.rend()):0x01ADC048]

如果vector有5個元素,它將正常工作。

[&(*it):0x007620A0][it->a:4][&(*vec.rend()):0x00762078]
[&(*it):0x00762098][it->a:3][&(*vec.rend()):0x00762078]
[&(*it):0x00762090][it->a:2][&(*vec.rend()):0x00762078]
[&(*it):0x00762088][it->a:1][&(*vec.rend()):0x00762078]
[&(*it):0x00762080][it->a:0][&(*vec.rend()):0x00762078]
---------------------------------------------
[&(*it):0x007620A8][it->a:13][&(*vec.rend()):0x00762078]
[&(*it):0x007620A0][it->a:4][&(*vec.rend()):0x00762078]
[&(*it):0x00762098][it->a:33][&(*vec.rend()):0x00762078]
[&(*it):0x00762090][it->a:2][&(*vec.rend()):0x00762078]
[&(*it):0x00762088][it->a:1][&(*vec.rend()):0x00762078]
[&(*it):0x00762080][it->a:0][&(*vec.rend()):0x00762078]

當它導致size超出容量時, push_back使迭代器無效

如果新的size()大於Capacity(),則所有迭代器和引用(包括過去的迭代器)都將失效。 否則,只有過去的迭代器是無效的。

基本上,如果必須push_back ,請確保提前reserve ,以免使迭代器無效。

您的程序很可能已崩潰。 您在操作容器的同時仍要對其進行迭代。

[&(*it):0x01ADC008][it->a:33][&(*vec.rend()):0x01ADC028]

您會看到垃圾“ 33”,而應該是“ 13”。

以及為什么還要嘗試取消引用最終迭代器

&(*vec.rend())

無論向量大小如何,這基本上都是垃圾。 這是未定義的行為,將使您的應用程序隨機崩潰。

正如陰影指出的那樣,請在迭代之前固定向量的大小,但是我仍然不確定如何修復您的代碼,因為您的示例還有其他會導致段錯誤的問題

對於正常(正向,非反向)向量迭代器,將向量插入向量會使指向插入點處或插入點之后的任何迭代器無效。 此外,如果必須調整向量的大小,則所有迭代器都會失效。

僅此一項就可以解釋您的問題,因為因為您沒有在向量中保留空間(通過調用vec.reserve(SIZE) ),所以任何push_back調用都可能觸發調整大小並使迭代器無效,當您執行此操作時,將導致未定義的行為然后嘗試使用它們。

但是,反向迭代器更為復雜,並且對反向迭代器沒有相同的保證,我相信任何插入都可能使它們無效。

在內部,反向迭代器在元素指向的元素之后保留一個正向迭代器。 取消引用時,反向迭代器將其遞減,以轉發迭代器並返回其解引用的值。 因此, rbegin()內部具有end()的副本,而rend()具有begin()的副本。 因此,上述用於前向迭代器失效的規則意味着,如果在反向迭代器位置之后最多一個元素的任意點出現插入,則至少反向迭代器將失效。 因此,如果您有一個迭代器在長度1的向量中指向索引0,則push_back將插入索引1,這將使迭代器無效。 如果然后繼續使用該迭代器(例如在后續的printf調用中取消引用該迭代器),則您將具有未定義的行為。

未定義的行為意味着任何事情都可能發生,並且通常不同的系統會產生不同的行為。 不要僅僅因為此代碼在您的系統上以預期的向量大小5運行就可以在其他系統上運行,就不要假設它。 任何調用未定義行為的代碼本質上都是脆弱的,應避免使用。

對我來說(運行Visual Studio 2015),無論矢量的大小如何,我都會在printf行上崩潰。 如果我調用vec.reserve(10)來消除大小調整無效問題,則僅當vec的長度最初為1時,它才會崩潰。

此外,即使您只是試圖從中獲取地址,也要在printf參數中取消引用vec.rend() ,這也是未定義的行為。 (我必須對此進行注釋以使您的代碼運行,否則即使沒有push_back調用,它也會每次崩潰。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM