"矢量迭代器不兼容"
'vector iterators incompatible'
这个问题在SO上被问了很多次,但答案不适用于我的情况,AFAICT。以下代码在命中i != std::end(observers_);
后立即触发错误。
void VisualGeometry::SignalPopPointFlags(const Point_2r& p,
const uint32_t msec_delay) const {
for(auto i = std::begin(observers_); i != std::end(observers_); ++i)
(*i)->SlotPopPointFlags(p, msec_delay);
}
查看<vector>
,以下触发错误:
void _Compat(const _Myiter& _Right) const
{ // test for compatible iterator pair
if (this->_Getcont() == 0
|| this->_Getcont() != _Right._Getcont())
{ // report error
_DEBUG_ERROR("vector iterators incompatible");
_SCL_SECURE_INVALID_ARGUMENT;
}
}
由于我没有比较来自不同容器的迭代器,所以第一次检查this->_Getcont() == 0
似乎是个问题,但我不知道如何判断。
如果我将begin(vec)/end(vec
我有点不知道这是怎么发生的。关于如何进行调试,有什么建议吗?
VisualGeometry类的设计目的是将它接收到的信号转发到任何正在观看它的对象
class VisualGeometry : public IGeometryObserver, public IObservableGeometry {
public:
void SlotPushSegmentFlags(const Segment_2r& s, const uint32_t flags,
const uint32_t msec_delay = 0) override;
void SlotPopSegmentFlags(const Segment_2r& s,
const uint32_t msec_delay = 0) override;
void SignalPushSegmentFlags(const Segment_2r& s, const uint32_t flags,
const uint32_t msec_delay = 0) const override;
void SignalPopSegmentFlags(const Segment_2r& s,
const uint32_t msec_delay = 0) const override;
/* snip */
private:
std::vector<IGeometryObserver*> observers_;
};
void VisualGeometry::SlotPushSegmentFlags(const Segment_2r& s,
const uint32_t flags,
const uint32_t msec_delay) {
SignalPushSegmentFlags(s, flags, msec_delay);
}
void VisualGeometry::SlotPopPointFlags(const Point_2r& p,
const uint32_t msec_delay) {
SignalPopPointFlags(p, msec_delay);
}
/* etc... */
首先要检查的是,在对vector
进行迭代时,是否正在修改它。
看看这是否消除了问题:
void VisualGeometry::SignalPopPointFlags(const Point_2r& p,
const uint32_t msec_delay) const {
auto obs = observers_;
for(auto i = std::begin(obs); i != std::end(obs); ++i)
(*i)->SlotPopPointFlags(p, msec_delay);
}
处理这类问题很棘手,通常是你有设计问题的迹象。
通常,在调用一个回调序列时,如果该回调能够到达您正在迭代的序列并更改它或其成员,则需要添加一些生存期管理代码,并确定在当前发送一个回调时发送另一个回调意味着什么,以及在调用回调时安装或卸载回调意味着哪里。
一个简单的规则是,"如果在安装回调时安装了回调,则不会得到回调",但如果卸载了回调,就不会被调用。
为了产生这种效果,我的回调往往是weak_ptr
s到std::function
s的容器。当你安装回调时,你传递一个std::function
,然后我将其复制到shared_ptr
中。我从中派生出一个weak_ptr
,并将其存储在回调容器中。
然后,我将shared_ptr
返回给正在安装回调的代码。这个shared_ptr
是生存期令牌:只要它(或它的副本)有效,我就会继续对它进行回调
在我的广播函数中,我首先扫描容器中过时的weak_ptr
,然后将容器复制到本地std::vector<std::weak_ptr<std::function<void(message)>>>
。
然后,我对这个容器进行迭代,执行.lock()
以获得std::shared_ptr<std::function<void(message)>>
,然后如果它有效,则调用它
如果我在广播时触发了广播,它就会发生。(如果这种情况经常发生,我会大发雷霆,但那是另一个问题)。如果有人添加回拨,我很好。如果有人删除回调,我很好。
如果是多线程的,那么在本地std::vector
上迭代时我不会被锁定,而是在清除无效的weak_ptr
s、克隆weak_ptr
s序列或向vector<weak_ptr<function<...>>>
添加/删除回调时被锁定。
- 不明白迭代器,引用和指针失效,一个例子
- 自定义 STL 兼容迭代器,用于迭代 2D 数组类的列
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 为什么 min_element() 返回最小元素的索引,而不是迭代器?
- 我从 std::set 得到const_iterator而不是迭代器
- 为什么向量的.at()成员函数返回引用而不是迭代器
- 如果我有一个指向矢量元素的指针,而不是迭代器,如何删除它?
- 对于使用 C 样式指针矢量化的循环,但不使用迭代器
- 使用循环(而不是迭代器)从向量中删除指针
- 将指针而不是迭代器传递到std ::复制
- 如何在不使用迭代器的情况下在 C++ 中打印地图
- C++模板不接受迭代器
- 容器不可知迭代器参数
- 为什么 void* 不是迭代器类型?
- 如何在不使用迭代器的情况下访问任何向量的第 i 个元素
- 为什么在达到容量后在向量中插入时,C++不处理迭代器?
- 我可以用cout而不是迭代器循环打印STL映射吗?
- 为什么 std::bitset 不附带迭代器?
- 字符串::擦除不接受迭代器?
- 是否有一个标准容器允许在不使迭代器无效的情况下插入元素