如何将 Vector<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]
push_back
导致size
超过容量时使迭代器失效:
如果new size()大于capacity(),则所有迭代器和引用(包括过端迭代器)都无效。否则,只有过末端迭代器失效。
基本上,如果必须使用push_back
,请确保提前使用reserve
,这样就不会使迭代器无效。
您的程序很可能崩溃了。你在操作容器的同时还在对其进行迭代。
[&(*it):0x01ADC008][it->a:33][&(*vec.rend()):0x01ADC028]
你可以看到垃圾'33',而它应该是'13'。
为什么要解引用end迭代器
&(*vec.rend())
无论向量大小,这基本上都是垃圾。这是一个未定义的行为,会随机导致应用程序崩溃。
作为影子指出修复向量大小迭代之前,但我仍然不确定如何修复你的代码,因为你的例子有其他问题,将导致段故障
对于普通的(正向的,而不是反向的)vector迭代器,插入vector后,指向插入点或插入点之后的任何迭代器将失效。此外,如果必须调整vector的大小,则所有迭代器都无效。
这本身就可以解释你的问题,因为你没有在你的向量中保留空间(通过调用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
调用)
- lower_bound()返回最后一个元素
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 使用运算符 [] 引用 std::vector 上最后一个元素时出现问题<>
- Lower_bound不适用于具有 3 个元素的向量的最后一个元素
- 检查 2D 网格的某个元素是否与另一个元素共享对角线、水平线或垂直线
- 仅显示链表的最后一个元素
- push_back通过自行创建的对象获取最后一个元素的向量
- 使用 map.end() 访问 map 的最后一个元素
- 如何知道地图中的最后一个元素是否被删除?
- 选择一个元素而不是一个对象的数组的原因
- std::矢量保存 只推送最后一个元素
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- 反转后不返回最后一个元素
- 如何在新数组较小时创建新数组并将旧数组的最后一个元素复制到新数组中?
- 访问 for_each 函数中的前一个元素
- 在 QListView 中显示最后一个元素
- 从 std::vector 中选择一个元素,而不是给定元素
- C++:在进行切片时对迭代器的约定,特别是对于访问最后一个元素并最终将其删除
- 遍历列表包含排除最后一个元素的内容
- 如何从一个无序集合中获取一个元素