gpt4 book ai didi

c++ - ' vector 迭代器不兼容'

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:29:41 25 4
gpt4 key购买 nike

此问题已在 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) 换成 vec.begin()/vec.end(),也会出现同样的问题。

我有点不知道这是怎么发生的。关于如何继续调试它有什么建议吗?

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秒。当你安装你的回调时,你传入一个 std::function ,然后我将其复制到 shared_ptr 中.我生成一个 weak_ptr关闭它,并将其存储在我的回调容器中。

然后我返回 shared_ptr到正在安装回调的代码。这shared_ptr是生命周期 token :只要它(或它的拷贝)有效,我就会继续对其进行回调。

在我的广播功能中,我首先扫描我的容器以查找过时的 weak_ptr s,然后将容器复制到本地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<...>>> 添加/删除回调时.

关于c++ - ' vector 迭代器不兼容',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18326628/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com