无效地将void表达式与线程和对象一起使用

invalid use of void expression with thread and an object

本文关键字:对象 一起 线程 void 表达式 无效      更新时间:2023-10-16

我想创建ahrs类中函数ahrs的线程。这个函数是一个无限循环,它一直在计算一些东西,并将这些计算放入变量中。我想把这些变量传递给我的PID

int main() {
    AHRS* a = new AHRS();
    std::thread ahrs(a->ahrs());
    PID* p = new PID();
    float pitch;
    while(1) {
        pitch = a->getPitch();
        std::cout << "pitch: " << pitch << " pid: " << p->getError(0, pitch, 1) << std::endl;
        usleep(100000);
    }   
}

但是我得到错误

main_ahrs.cpp: In function ‘int main()’:
main_ahrs.cpp:26:28: error: invalid use of void expression

我的ahrs.cpp看起来是这样的:

#include "AHRS.h"
AHRS::AHRS() {
    //something
}
AHRS::~AHRS() {}
void AHRS::ahrs() {
    //something
    while(1) {
        //something
    }
}
float AHRS::getPitch() {
    //return something
}
float AHRS::getRoll() {
    //return something
}
float AHRS::getYaw() {
    //return something
}

感谢您的帮助

a->ahrs()

函数不是这样命名的。这就是你如何调用一个表达式并将其结果用于某些事情。函数的结果是void类型的(也就是说,没有一个(,所以将此函数调用用作表达式(当然对于函数引用/对象/句柄/包装器/指针也是如此!(是行不通的。

该函数称为AHRS::ahrs

更复杂的是,它是一个成员函数,因此必须绑定隐式this参数,如下所示:

std::thread ahrs(std::bind(&AHRS::ahrs, a));

绑定创建了一种伪函数引用,它已经为您整理了第一个参数,因此您(或者在本例中,thread代码,它没有能力或希望猜测对象实例应该是什么(不需要

不过,方便的是,thread可以为您进行绑定,因此:

std::thread ahrs(&AHRS::ahrs, a);

应该足够了。

这样尝试:

#include <functional>

然后:

std::thread ahrs(std::bind(&AHRS::ahrs, a));

按照您的方法,您正在调用a->ahrs()方法,该方法返回void。您必须向std::thread传递一些可以调用的东西:函数指针或类似的东西,而不是void

在我的建议的这种情况下,您将把std::bind的返回传递给std::thread,这是一个用指向方法的指针和指向AHRS对象的指针构建的可调用对象。

Lambda是你的朋友。

int main() {
  AHRS* a = new AHRS();
  std::thread ahrs(a->ahrs());

上面所做的是调用a->ahrs()(在main中(,获取其返回值并将其传递给thread构造函数。这不是你想要的。

相反:

  AHRS* a = new AHRS();
  std::thread ahrs([a]{a->ahrs();});

将创建一个包含"执行a->ahrs()的调用"的闭包(或lambda(。

然后,它将该闭包传递给std::thread,后者在另一个线程上运行它。

[a]表示"这是一个闭包,它捕获了a的(副本("。然后主体{a->ahrs();}说明闭合的作用。

一般来说,将lambdas传递给std::thread比传递备选方案更容易推理。移动参数需要C++14才能工作,这是一个适度的问题。

使用CCD_ 22或CCD_。在这种情况下,我更喜欢传递代码而不是传递数据,传递lambda闭包基本上就是传递代码。