我正在为嵌入式做一些C++库,我需要创建一个回调功能。我希望能够注册成员函数和lambda。我尝试了这个(简化的),但没有太多运气:
#include <iostream>
#include <functional>
#include <vector>
typedef const std::function<void (int)> connection_handler_t;
std::vector<connection_handler_t*> connectionHandlerList;
void addConnectionHandler(connection_handler_t& h) {
connectionHandlerList.push_back(&h);
}
void runConnectionHandlers() {
std::cout << "Running registered connection handlers" << std::endl;
for (auto& handler : connectionHandlerList) {
(*handler)(16);
}
}
int main() {
std::cout << "testing vector" << std::endl;
addConnectionHandler([=](int i) {
std::cout << "a: " << i << std::endl;
});
addConnectionHandler([=](int i) {
std::cout << "b: " << i << std::endl;
});
runConnectionHandlers();
}
我的输出是:
testing vector
Running registered connection handlers
b: 16
b: 16
我的预期结果是:
testing vector
Running registered connection handlers
a: 16
b: 16
为什么它总是运行相同的最后一个lambda X次?我正在为Java服务器开发客户端库,所以我是C++的新手
谢谢
发布于 2018-06-15 08:18:07
这是因为所显示的代码表现出未定义的行为。例如,使用我的编译器,我得到了您期望的结果,但这只是随机的。
addConnectionHandler([=](int i) {
std::cout << "a: " << i << std::endl;
});
这将创建一个临时对象,并将其传递给addConnectionHandler()
。此函数返回后,此临时对象将被销毁。
addConnectionHandler()
内幕
connectionHandlerList.push_back(&h);
这将在一个向量中保存一个指向传入对象的指针。
不幸的是,正如我所解释的,传入的对象是一个临时对象,一旦此函数返回,它就会被销毁。保存的指针指向已销毁的对象。
下面的代码尝试使用保存的指针来取消引用并调用类型擦除的lambda。然而,由于这些指针是悬空的,并且指向被销毁的对象,这会导致未定义的行为。您可能会在每次调用程序时看到不同的行为,甚至崩溃。
这里不需要使用指针。只需创建一个包含std::function
对象的向量,并将输入的std::function
按原样直接推送到该向量中。在这个用例中不需要指针。
https://stackoverflow.com/questions/50867534
复制相似问题