我有以下代码,在信号回调过程中删除信号:
#include <iostream>
#include <boost/signals2/signal.hpp>
struct Foo {
boost::signals2::signal<void(int)> signal;
};
std::vector<Foo> foos;
foos.emplace_back(Foo());
std::vector<int> values;
auto connection = boost::signals2::scoped_connection(foos[0].signal.connect([&](int x) {
foos.clear(); // delete the foos here, where we will be calling from below
values.emplace_back(1);
}));
foos[0].signal(1);
std::cout << "values.size()=" << values.size() << "\n";我只是幸运地在这个“工作”(就像它是未定义的行为),还是有什么神奇的指针计数在signals2,阻止我的脚?
发布于 2022-01-15 17:13:22
// delete the foos here, where we will be calling from below这是个误导性的评论。删除(clear())仅在发出信号后发生,因此控制流与代码行相反。
在我看来,这段代码看起来是有效的,除非您从信号处理程序中销毁connection (例如connection.release();)。即使这样,它也可能是安全的,但它将取决于处理程序迭代的实现细节。我怀疑它仍然会很好,因为Signals2库明确地知道线程,所以逆流必须很好(在信号调用期间将处理程序添加到相同的槽中)。
在signals2中是否有什么神奇的指针在阻止我把脚踢掉?
Signals2中神奇的引用计数是您已经拥有的比特:scoped_connection,它将在最后一个副本超出范围时自动断开连接。
与所示代码不完全相关: 当然,通过使用things
std::vector<shared_ptr<Foo> >,您可以在自己的实体上拥有相同的工具。如果对foos元素的引用/迭代器需要是稳定的,请使用std::list或std::deque(仅包含前/后插入/删除)。
下面是我对通过UBsan/ASan进行优化和不进行优化的代码的看法:
住在Coliru
#include <boost/signals2/signal.hpp>
#include <iostream>
namespace s2 = boost::signals2;
struct Foo {
s2::signal<void(int)> onEvent;
};
int main() {
std::vector<Foo> foos(3);
std::vector<int> values;
std::cout << "before values.size()=" << values.size() << "\n";
s2::scoped_connection connection =
foos.back().onEvent.connect([&](int x) {
foos.clear(); // delete the foos here
values.emplace_back(1);
connection.release();
});
foos.back().onEvent(1);
std::cout << "after values.size()=" << values.size() << "\n";
}打印
before values.size()=0
after values.size()=1https://stackoverflow.com/questions/70722700
复制相似问题