繁体   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