std::包含 std::函数回调的多个包装器的向量不起作用

std::vector of multiple wrappers containing std::function callbacks does not work

本文关键字:std 向量 不起作用 包装 回调 包含 函数      更新时间:2023-10-16

我正在编写一个包含 std::function<> 的包装器MyTest,用于存储回调。 包装器包含在 shared_ptr<> 的 std::vectortests中。 emplace_back向量中的单个包装器有效,即可以触发 std::function 回调。如果我在向量中有两个对象,则只有最后一个对象回调有效。

以下是我的课程:

typedef function<void(const uint64_t &)> CallBackFunc_t;
class MyWheel
{
private:
class test
{
private:
const CallBackFunc_t &callback;
public:
test(const CallBackFunc_t &cb);
bool work();
};
public:
vector<shared_ptr<test>> tests;
int addTest(const CallBackFunc_t &test_callback);
void spin(void);
};

class MyTest
{
private:
int handle = -1;
MyWheel &wheel;
public:
MyTest(MyWheel &whl);
int setCallback(const CallBackFunc_t &callback);
};

和来源。

MyWheel::test::test(const CallBackFunc_t &cb) : callback(cb)
{
}
bool MyWheel::test::work()
{
callback(0);
return true;
}
int MyWheel::addTest(const CallBackFunc_t &test_callback)
{
tests.emplace_back(new test(test_callback));
return (int)(test.size()-1);
}
void MyWheel::spin(void)
{
for(vector<shared_ptr<test>>::iterator test = tests.begin(); test != tests.end(); ++test)
{
(*test)->work();
}
}
MyTest::MyTest(MyWheel &whl) : wheel(whl)
{
};
int MyTest::setCallback(const CallBackFunc_t &callback)
{
if(handle < 0)
{
handle = wheel.addTest(callback);
}
return handle;
}

用法:


MyWheel wh;
MyTest t1(wh);
MyTest t2(wh);
t1.setCallback([&](const uint64_t &e) {
cout <<"1rn";
});
t2.setCallback([&](const uint64_t &e) {
cout <<"2rn";
});
while(true)
{
wh.spin();
}

我希望在运行时打印"1"和"2",但只有"2"是...... 我做错了什么?

你需要通过复制存储回调:

class test
{
private:
CallBackFunc_t callback; // <---- make a copy of callback
public:
test(const CallBackFunc_t &cb);
bool work();
};

现在你有未定义的行为,因为你正在存储对回调的引用,该回调在此表达式的末尾被销毁:

t1.setCallback([&](const uint64_t &e) {
cout <<"1rn";
}); // it causes dangling reference

如果你想在test中保留对回调的引用,你需要在调用setCallback之前将它们创建为Lvalues:

std::function<void (const uint64_t& )> callback1 = [](const uint64_t &e)  {
cout <<"1rn";
};
t1.setCallback(callback1);
std::function<void (const uint64_t& )> callback2 = [](const uint64_t &e)  {
cout <<"2rn";
};
t2.setCallback(callback2);

嗨,rafix07,感谢您的示例! 是的,这确实起到了作用,并且在捕获列表中添加 & 使得访问定义回调函数的变量成为可能。

bool var1 = false;
std::function<void (const uint64_t& )> callback1 = [&](const uint64_t &e)  {
cout <<"1rn";
var1 = true;
};
t1.setCallback(callback1);