- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用循环和迭代器从双端队列中删除一个元素。我正在关注 online examples但看到一个错误。
我使用的是 g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)。
代码如下:
#include <iostream>
#include <deque>
using namespace std;
// Display the contents of a queue
void disp_deque(deque<int>& deque) {
cout << "deque contains: ";
for (auto itr = deque.begin(); itr!=deque.end(); ++itr)
cout << *itr << ' ';
cout << '\n';
}
int main(int argc, char** argv) {
deque<int> mydeque;
// Put 10 integers in the deque.
for (int i=1; i<=10; i++) mydeque.push_back(i);
disp_deque(mydeque);
auto it = mydeque.begin();
while (it!=mydeque.end()) {
cout << "Checking " << *it << ',';
// Delete even numbered values.
if ((*it % 2) == 0) {
cout << "Deleting " << *it << '\n';
mydeque.erase(it++);
disp_deque(mydeque);
} else ++it;
}
}
这非常简单 - 创建一个包含 10 个元素的列表并删除偶数元素。
注意以下几点(绒毛除外):
if ((*it % 2) == 0) {
mydeque.erase(it++);
} else it++;
这是使用迭代器删除的推荐方法,这样您的迭代器就不会像上面链接中提到的那样失效。
但是,当我运行它时,我得到以下信息:
$ ./test
deque contains: 1 2 3 4 5 6 7 8 9 10
Checking 1,Checking 2,Deleting 2
deque contains: 1 3 4 5 6 7 8 9 10
Checking 3,Checking 4,Deleting 4
deque contains: 1 3 5 6 7 8 9 10
Checking 5,Checking 6,Deleting 6
deque contains: 1 3 5 7 8 9 10
Checking 7,Checking 8,Deleting 8
deque contains: 1 3 5 7 9 10
Checking 10,Deleting 10
deque contains: 1 3 5 7 9
Checking 10,Deleting 10
deque contains: 1 3 5 7
Checking 0,Deleting 0
deque contains: 1 3 5
Checking 0,Deleting 0
deque contains: 1 3
Checking 0,Deleting 0
deque contains: 1
Checking 0,Deleting 0
deque contains:
Checking 0,Deleting 0
Segmentation fault (core dumped)
翻了一下,貌似还不错,直到把8删掉了,其实9号是直接跳过了,根本没检查过!我期望应该发生的是:
$ ./test
deque contains: 1 2 3 4 5 6 7 8 9 10
Checking 1,Checking 2,Deleting 2
deque contains: 1 3 4 5 6 7 8 9 10
Checking 3,Checking 4,Deleting 4
deque contains: 1 3 5 6 7 8 9 10
Checking 5,Checking 6,Deleting 6
deque contains: 1 3 5 7 8 9 10
Checking 7,Checking 8,Deleting 8
deque contains: 1 3 5 7 9 10
Checking 9,Checking 10,Deleting 10
deque contains: 1 3 5 7 9
事实上,这正是我将代码更改为:
if ((*it % 2) == 0) {
it=mydeque.erase(it);
} else it++;
那么,为什么一种方法有效,而另一种方法无效呢?谁能解释一下?
即使我创建了一个临时迭代器来删除,我也会看到完全相同的问题输出:
while (it!=mydeque.end()) {
cout << "Checking " << *it << ',';
auto tmp_it = it++;
// Delete even numbered values.
if ((*tmp_it % 2) == 0) {
cout << "Deleting " << *tmp_it << '\n';
cout << "IT before delete: " << *it << '\n';
mydeque.erase(tmp_it);
cout << "IT after delete: " << *it << '\n';
disp_deque(mydeque);
}
}
这里我将它的拷贝存储在 tmp_it 中,然后递增它。我添加了更多调试语句并看到了一些非常奇怪的东西:
...
deque contains: 1 3 5 6 7 8 9 10
Checking 5,Checking 6,Deleting 6
IT before delete: 7
IT after delete: 7
deque contains: 1 3 5 7 8 9 10
Checking 7,Checking 8,Deleting 8
IT before delete: 9
IT after delete: 10
deque contains: 1 3 5 7 9 10
Checking 10,Deleting 10
IT before delete: 10
IT after delete: 10
...
然而,删除元素 8 使其指向元素 10,跳过 9!在以前的删除中,它指向前一个元素(例如,当删除 6 时,它指向删除前后的 7)。
我查看了 deque 的实现并在“迭代器有效性”下查看以下内容(强调我的):
Iterator validity If the erasure operation includes the last element in the sequence, the end iterator and the iterators, pointers and references referring to the erased elements are invalidated. If the erasure includes the first element but not the last, only those referring to the erased elements are invalidated. If it happens anywhere else in the deque, all iterators, pointers and references related to the container are invalidated.
那么这是否意味着在我的代码中,我的迭代器正在失效,即使我在它被删除之前对其进行了后递增?即我删除的迭代器以外的迭代器正在失效?
如果是这样,那很好,但它似乎是一个鲜为人知的错误。这意味着 common使用双端队列时,循环内迭代器删除的实现无效。
最佳答案
来自 deque::erase()
上的 cppreference :
All iterators and references are invalidated, unless the erased elements are at the end or the beginning of the container, in which case only the iterators and references to the erased elements are invalidated.
所有 迭代器。他们全部。当您这样做时:
mydeque.erase(it++);
后递增it
并不重要,新的迭代器也会失效。这正是 erase()
返回的原因:
Iterator following the last removed element. If the iterator pos refers to the last element, the end() iterator is returned.
这样你就可以:
it = mydeque.erase(it); // erase old it, new it is valid
尽管更好的方法是使用删除-删除习惯用法来完全避免这种错误来源:
mydeque.erase(
std::remove_if(mydeque.begin(), mydeque.end(), [](int i){return i%2 == 0; }),
mydeque.end()
);
另见 this question有关迭代器失效的更多信息。
关于c++ - std::deque 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32593667/
这个问题在这里已经有了答案: Is using std::deque or std::priority_queue thread-safe? [duplicate] (3 个答案) Thread s
我是一名学生,我的操作系统类(class)项目有一点问题,这对于作业规范本身来说有点多余: 虽然我可以将 100 万个双端队列推送到我的双端队列中,但我无法推送约 1000 万或更多。 现在,在实际的
std::deque 在 CppReference 中有很好的记录,但是 boost::deque 的 documentation看起来和标准的一样,只是增加了一些方法,比如nth和index_of。
Scala 是否具有类似于 Java Deque 或 Python deque 的双面队列? 我在 Scala 2.12 API 中只看到 Stack 和 Queue 但只想仔细检查一下。 最佳答案
好的,我正在实现一个与 Apple 的日历应用程序非常相似的日历。我的 UICollectionView 中有多种类型的单元格。我有垂直线单元格、水平线单元格、现在线单元格和事件单元格。 每当我滚动时
目前在我的项目中我有两个静态方法PushObjects 和ProcessObject。 PushObject 方法将数据推回静态双端队列,此方法可由多个线程访问,但 ProcessObject 始终由
使用 http://www.cppreference.com/wiki/stl/deque/insert作为引用,我在某些位置将值插入双端队列。 例如,如果双端队列 A 是: a, b, d, e,
Python 的 collections.deque有一个 maxlen 参数,这样 [...] the deque is bounded to the specified maximum lengt
这是我的第一个问题,希望大家都好。我必须编写双端队列或双端队列的数组实现,但在理解前面方法的入队元素时遇到了一些麻烦,我通过摆弄了一下让它工作,但我仍然很难理解逻辑: void addAtFront(
我试图解决 Java Deque 上的 HackerRank 问题。除了具有 100,000 个输入的案例之外,我的代码通过了所有案例。 问题:在这个问题中,给你 N 个整数。您需要在大小为 M 的所
我正在编写 Deque 以便能够从 Front 和 Rear 中添加和删除....我认为我的逻辑是错误的,但我无法弄清楚!因为当我从前面插入时,它必须从后面移除,但也从前面移除。 你会检查我的代码并帮
我在使用 deque 容器时有些困惑。 我将 vector 与 deque 进行了比较,我动态地输入了 Integer 值并观察到在几次插入之后 vector 的对象开始四处移动并且地址已被更改,这似
由于我对内存有严格的要求,因此在从双端队列的开头删除一个范围后,我尝试使用deque::shrink_to_fit。但是,它不起作用,我只看到libstdc++使用带有副本的swap技巧实现了shri
我需要为继承到 deque 的类添加功能,但更喜欢看到 collections.deque 中的代码来实现一个新类 final。 >>> from _collections import deque,
本文实例讲述了python3 deque 双向队列创建与使用方法。分享给大家供大家参考,具体如下: 创建双向队列 ?
考虑以下 C++ 程序: #include #include using namespace std; int main() { deque d(30000000); cout
尝试使用 Deque 数据结构来回答一个编程问题,以查找乘积小于目标的所有子数组。 如上所述,我想使用 Deque 数据结构。我查看了用法,认为我做对了,但是使用了 const Deque = req
双端队列实现我实现了一个通用的 Deque 数据结构。 请检查此实现 这个错误对我来说没有意义,请告诉我一点信息 import java.util.NoSuchElementException; im
我需要编写自己的 Deque 类,并且必须使用双向链表实现来存储数据。问题是编写方法pushfromLeft(Thing thing),它将插入到双端队列的左侧。以下是我迄今为止所拥有的,但似乎不起作
标准说: A deque is a sequence container that supports random access iterators (27.2.7). In addition, it
我是一名优秀的程序员,十分优秀!