为什么在调用erase和push_back函数后,下列元素同时出现在这个c++ vector的头和尾?

Why does the following element appear at both the head and tail of this c++ vector after a call to erase and push_back?

本文关键字:c++ vector push erase 调用 back 函数 为什么 元素      更新时间:2023-10-16

我试图理解为什么以下代码的行为方式:

std::vector<int*> k;
for (int i = 0; i < 5; ++i) k.push_back(new int(i));
for (int i = 0; i < k.size(); ++i)
    std::cout << "k[" << i << "]: " << *k[i] << "@" << k[i] << ", ";
std::cout << std::endl;
for (int i = 0; i < k.size(); ++i) {
    int* p = k[i];
    delete p;
    if (i >= 2) {
        k.erase(k.begin(), k.begin() + i);
        k.push_back(new int(5));
        break;
    }
}
for (int i = 0; i < k.size(); ++i)
    std::cout << "k[" << i << "]: " << *k[i] << "@" << k[i] << ", ";
std::cout << std::endl;

当我运行这个,我们第一次打印k的内容,我看到这样:

[0]: 0@0x1774e010, k[1] 1@0x1774e050, k[2]: 2@0x1774e030, k[3]: 3@0x1774e070, k[4]: 4@0x1774e0c0

这正是我所期望的。然后在擦除和push之后,我希望前两个元素消失,最后三个元素被移动,第5个元素出现在最后。然而,我得到的却是这个:

k[0]: 5@0x1774e030, k[1]: 3@0x1774e070, k[2]: 4@0x1774e0c0, k[5]: 5@0x1774e030,

我确实看到k[5]出现在其他元素移动后的末尾,但我不理解为什么它也出现在第一个元素。

vector::erase的第二个参数是end迭代器后的。这是标准c++库中迭代器范围的典型形式。

所以,当i == 2语句k.erase(k.begin(), k.begin() + i)只擦除前两个元素,留下你刚刚删除的一个仍然在向量中。当您尝试使用已删除的指针时,这会导致错误的结果。

(从技术上讲,执行erase也是未定义的行为,因为它涉及读取已删除的指针)。

可能,你看到k[0]: 5@0x1774e030而不是随机垃圾的原因是你的new int重新分配到与delete相同的空间;我猜那行k[5]:k[3]:的错别字