顺序执行的代码转换成多线程执行;

艰难地进行了几次变迁, 整理问题如下:
原本代码如下:

if (left_cam_.is_capturing()) {if (!take_and_send_image(left_cam_,left_info)) ROS_WARN("USB camera did not respond in time.");
}
if(right_cam_.is_capturing()){if(!take_and_send_image(right_cam_, right_info)) ROS_WARN("USB camera did not respond in time.");
}

想要改成 多线程的形式:

if (left_cam_.is_capturing() &&right_cam_.is_capturing()) {std::thread takeLeftThread(&take_and_send_image,left_cam_,left_info);std::thread takeRightThread(&take_and_send_image,right_cam_,right_info);takeLeftThread.join();takeRightThread.join();std::cout << "Finished Capture Left and Right " << endl;
}

报错如下:

 error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say '&usb_cam::UsbCamNode::take_and_send_image' [-fpermissive]
|   344 |         std::thread takeLeftThread(&take_and_send_image,left_cam_,left_info);

感觉这个问题很复杂的样子, stackoverflow上大家也都在各种讨论, SO上的讨论 错误信息翻译过来就是:

ISO C ++禁止使用不合格或带括号的非静态成员函数的地址形成指向成员函数的指针

我看了一下大家的分析, 简单地翻译过来如下:

作者遇到的问题是代码在下面这行时报错如上:

fPtr = &(myfoo::foo); 

高分解答是希望作者把这行代码修改为如下:

fPtr = &myfoo::foo;

详细的解释里, 其中有一句很重要的话:

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses [...]

第一次觉得英语太难了... 翻译过来大概是 指向成员函数的指针只有在 有显示引用&以及该函数没有被括号括起来的情况下 才能形成,stackoverflow上的楼主遇到的就是这个问题,大家讨论的也更深一点, 也就是说为什么会有这个设定,以及这个设定的好处; (想要了解的可以看网页上第二个回答,这里不再赘述,主要也不保证我能理解对[捂脸哭]);

虽然和我的实际情况,不是特别一样,其实效果是差不多的, 我的是把非静态成员函数直接用于新建线程,这样无法形成一个有效的pointer, 因此添加上类名之后,错误消失;

改动后的代码如下:

if (left_cam_.is_capturing() &&right_cam_.is_capturing()) {std::thread takeLeftThread(&Usb_cam_node::take_and_send_image,left_cam_,left_info);std::thread takeRightThread(&Usb_cam_node::take_and_send_image,right_cam_,right_info);takeLeftThread.join();takeRightThread.join();std::cout << "Finished Capture Left and Right " << endl;
}

修改后的代码又遇到了下面这个问题:

In instantiation of 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = bool (usb_cam::UsbCamNode::*)(usb_cam::UsbCam&, usb_cam::UsbCamNode::camera_node_info&); _Args = {usb_cam::UsbCam&, usb_cam::UsbCamNode::camera_node_info&}; <template-parameter-1-3> = void]':
|nodes/usb_cam_node.cpp:344:88:   required from here
| recipe-sysroot/usr/include/c++/9.1.0/thread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
|   120 |           typename decay<_Args>::type...>::value,
|       |                                            ^~~~~

问题的主要提示是这句话, 即std::thread 的参数在转换成rvalues后变得不可调用

static assertion failed: std::thread arguments must be invocable after conversion to rvalues

这里说一下我的函数定义:

bool take_and_send_image(UsbCam &cam, camera_node_info &camera_info)
{//DO somethingreturn 0;
}

上面定义中的形参分别是类UsbCam和结构体camera_node_info;

看了一下网上的帖子,总结一下, 大概有两种写法会触发上面的错误:

触发invocable的第一种错误类型

第一种是在使用非静态成员函数创建线程的时候,没有添加类的实例化对象进去, 也就是我上面的代码中如果不添加 this, 则会报此错误;

大神们使用了std::invoke()来举例:

If you're using invoke on non-static member, you have to pass instance of Class, otherwise you will take another overload which won't identify first argument as invokable.

当用非静态函数创建invoke时, 需要将其对应的实例化对象一起传入, 否则,函数将会重新进行重载,导致传参变成invokable,即不可以调用;

错误代码为:

 foo f;std::thread t5(&foo::bar);//这里会报错

正确的代码如下:

 foo f;std::thread t5(&foo::bar, &f);//这里的f必须传入进来

第二种会触发上面这个错误的情况是下面的情况,传入参数的问题;

为了解决刚才的问题,我将代码改成了下面的形式, 给每个传入的参数添加了 引用符号, 但是依然报错;

std::thread takeLeftThread(&UsbCamNode::take_and_send_image,this, &left_cam_,&left_info);
std::thread takeRightThread(&UsbCamNode::take_and_send_image,this, &right_cam_,&right_info);

按照大神们的解答, 这种以引用符号的形式并不能将该对象进行传递, 因此需要借助于std::ref();

std::thread takeLeftThread(&UsbCamNode::take_and_send_image,this, std::ref(left_cam_),std::ref(left_info));
std::thread takeRightThread(&UsbCamNode::take_and_send_image,this, std::ref(right_cam_),std::ref(right_info));

将代码修改成上面的部分后,即可编译通过;具体的解释可以浓缩成一句话:

std::ref使用于那些只能使用值传递而不能使用引用传递的地方;

有一点一知半解,更详细的可以参考这里
到此,问题算是解决了,莫名感觉到一阵空虚.....

并发编程这条路太艰辛了,我上面的总结如果有问题,还麻烦大神们不吝赐教,一定指出来;谢谢!!

REF:

禁止获取不合格或括号内的非静态成员函数的地址

C++官网thread解释

std::thread的使用相关推荐

  1. C++11 新特性之std::thread

    C++11 新特性之std::thread 原文:https://blog.csdn.net/oyoung_2012/article/details/78958274 从C++11开始,C++标准库已 ...

  2. std thread

    不要用std::thread写裸线程 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/daan_112211/article/details/1908 ...

  3. 并发,std::thread

    2019独角兽企业重金招聘Python工程师标准>>> std::thread  定义一个线程对象,并管理关联的线程 备注: 你可以使用 thread 对象来观察和管理在应用程序中的 ...

  4. 【多线程】C++11进行多线程开发 (std::thread)

    文章目录 创建线程 std::thread 类 使用join() 使用 detach() 警惕作用域 线程不能复制 给线程传参 传递指针 传递引用 以类成员函数为线程函数 以容器存放线程对象 互斥量 ...

  5. C++11学习笔记-----线程库std::thread

    在以前,要想在C++程序中使用线程,需要调用操作系统提供的线程库,比如linux下的<pthread.h>.但毕竟是底层的C函数库,没有什么抽象封装可言,仅仅透露着一种简单,暴力美 C++ ...

  6. C++ std::thread 和 std::jthread 使用详解 (含C++20新特性)

    目录 std::thread std::thread 构造函数 观察器 操作 std::jthread std::jthread 构造函数 观察器 操作 停止记号处理 管理当前线程的函数 yield( ...

  7. std::jthread与std::thread的区别

    特性上,std::jthread相比std::thread主要增加了以下两个功能: 1.std::jthread对象被destruct时,会自动调用join,等待其所表示的执行流结束. 2.支持外部请 ...

  8. c++11仔细地将参数传递给线程std::thread

    要将参数传递给线程的可关联对象或函数,只需将参数传递给std::thread构造函数. 默认情况下,所有的参数都将复制到新线程的内部存储中. 看一个例子: 给线程传递单个参数 #include < ...

  9. std::thread 不 join

    std::thread 构造之后 使用 detach.就可以了

  10. C++11并发编程:多线程std::thread

    一:概述 C++11引入了thread类,大大降低了多线程使用的复杂度,原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植,对应多线程代码也必须要修改.现在在C++11中只需使用语 ...

最新文章

  1. 【POJ】2828 Buy Tickets(线段树+特殊的技巧/splay)
  2. 蚂蚁金服发布「定损宝」,推动图像定损技术在车险领域的应用
  3. python中不具备np_Python中np.random.multivariate_normal问题?
  4. 机器人学习--智能移动机器人的有关技术演讲(浙大-熊蓉教授-2018年)
  5. 基于神经网络模型的文本语义通顺度计算研究-全文复现(还没弄完)
  6. history模式监听_面试题:VueRouter中的 hash 模式和 history 模式有什么区别
  7. 树莓派 摄像头 php,树莓派3 之 USB摄像头安装和使用
  8. 统计学习方法笔记(李航)———第四章(朴素贝叶斯法)
  9. byte比较_浅谈Byte-Level BPE
  10. 配置网络策略中的 NAP 条件
  11. 蓝桥杯2013c++真题:颠倒的价牌
  12. loadruner知识点小结
  13. Spring系列技术实战(项目搭建、知识点总结)
  14. java课设超市收银系统_超市收银系统java课程设计.doc
  15. 人力资源管理-人际交往中的6个心理效应
  16. python—武汉市2021年新房数据分析
  17. 基于SDN的访问控制模块实现
  18. 纳秒脉冲等离子体放电
  19. c++对8位灰度图进行二值化处理
  20. 《 Matlab_Simulink动力学系统建模仿真》及 ‘///’动力学 达朗贝尔原理、虚位移原理、朗格朗日方程...

热门文章

  1. bzoj 1630 2023: [Usaco2005 Nov]Ant Counting 数蚂蚁(有重复元素的组合数)
  2. javascript学习之利用方向键控制div模块的移动
  3. golang 安装 guru vscode 安装失败
  4. 手机页面图片显示高低不一致
  5. 虚拟机网络连接模式中桥接模式和NAT模式的区别
  6. UML 统一建模语言Unified Modeling Language (UML)
  7. 流程平台:示例流程 - 主机申请审批流程
  8. [转载] Python Pandas 的 all和any方法
  9. Spring注解浅入浅出——不吹牛逼不装逼
  10. web自动化测试python+selenium学习总结----selenium安装、浏览器驱动下载