首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >保存在向量中的C++ Lambda多次执行

保存在向量中的C++ Lambda多次执行
EN

Stack Overflow用户
提问于 2018-06-15 08:08:17
回答 1查看 115关注 0票数 1

我正在为嵌入式做一些C++库,我需要创建一个回调功能。我希望能够注册成员函数和lambda。我尝试了这个(简化的),但没有太多运气:

代码语言:javascript
复制
#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();
}

我的输出是:

代码语言:javascript
复制
testing vector
Running registered connection handlers
b: 16
b: 16

我的预期结果是:

代码语言:javascript
复制
testing vector
Running registered connection handlers
a: 16
b: 16

为什么它总是运行相同的最后一个lambda X次?我正在为Java服务器开发客户端库,所以我是C++的新手

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-15 08:18:07

这是因为所显示的代码表现出未定义的行为。例如,使用我的编译器,我得到了您期望的结果,但这只是随机的。

代码语言:javascript
复制
addConnectionHandler([=](int i) {
    std::cout << "a: " << i << std::endl;
});

这将创建一个临时对象,并将其传递给addConnectionHandler()。此函数返回后,此临时对象将被销毁。

addConnectionHandler()内幕

代码语言:javascript
复制
connectionHandlerList.push_back(&h);

这将在一个向量中保存一个指向传入对象的指针。

不幸的是,正如我所解释的,传入的对象是一个临时对象,一旦此函数返回,它就会被销毁。保存的指针指向已销毁的对象。

下面的代码尝试使用保存的指针来取消引用并调用类型擦除的lambda。然而,由于这些指针是悬空的,并且指向被销毁的对象,这会导致未定义的行为。您可能会在每次调用程序时看到不同的行为,甚至崩溃。

这里不需要使用指针。只需创建一个包含std::function对象的向量,并将输入的std::function按原样直接推送到该向量中。在这个用例中不需要指针。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50867534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档