从 C++ 中的函数返回数组

Returning Arrays from functions in C++

美好的一天 :) 我正在编写一个代码,用于从加速度计和陀螺仪获取俯仰角、偏航角和滚动角。为了创建一个看起来更简洁、易于理解的代码,我求助于创建两个不同的函数。一个用于计算 Pitch Yaw 和 Roll 的陀螺仪,另一个用于加速度计,它也做同样的事情。

float *readGyro(){
    /*get data from sensor here*/
    float gyroAngles[4]={gyroPitch,gyroRoll,gyroYaw};
    float* gyroPRY=gyroAngles;
    return gyroPRY;
}

float *readAccel(){
    /*get data from sensor here*/
    float accelAngles[4]={accelPitch,accelRoll,accelYaw};
    float* accelPRY=accelAngles;
    return accelPRY;
}

正如您在上面看到的,我将函数的输出存储到一个数组中,以传递给主函数。基本上指针被传递了。然而,在从传递的指针访问值时,打印了恒定的垃圾值(在我移动 IMU 时不变)(例如 2.38221e-44 和 -3.84146e-06)。我通过打印这些函数中的值检查了陀螺仪和加速度计函数的输出,它们很好。

int main(void){
    float *accelData;
    float *gyroData;

    while(1){
    accelData=readGyro();
    gyroData=readAccel();

    float accelPitch=*(accelData);
    float accelRoll=*(accelData+1);
    float accelYaw=*(accelData+2);

    float gyroPitch=*(gyroData);
    float gyroRoll=*(gyroData+1);
    float gyroYaw=*(gyroData+2);

    cout << "AccelPitch=" << accelPitch <<endl;
    cout << "AccelRoll=" << accelRoll <<endl;
    cout << "AccelYaw=" << accelYaw <<endl;
    cout << "GyroPitch=" << gyroPitch <<endl;
    cout << "GyroRoll=" << gyroRoll <<endl;
    cout << "GyroYaw=" << gyroYaw <<endl;

    }
}

我找不到我的代码有什么问题。在此之前,我查阅了很多参考资料。但是我仍然无法解决它。非常感谢您的帮助:)

您正在做的事情永远不会奏效,因为您正在 return 将指针指向 readGyroreadAccel 的堆栈。当这些函数退出时,堆栈的那部分将被回收,您将留下未定义的行为。

一种方法是分配数组并 return 它,但是你自己也不得不删除该分配。

您可以为所需参数创建 2 个结构并将它们传递到您的函数中。这样函数就可以写在某个地方,在它们 return.

之后会持续存在

例如

#include <iostream>

using std::cout;
using std::endl;

struct gyro_data_t
{
    float pitch;
    float roll;
    float yaw;
};

struct accel_data_t
{
    float pitch;
    float roll;
    float yaw;
};

void readGyro(gyro_data_t* gd)
{
    /*get data from sensor here*/
    gd->pitch = 1.0f;
    gd->roll = 1.1f;
    gd->yaw = 1.2f;
}

void readAccel(accel_data_t* ad)
{
    /*get data from sensor here*/
    ad->pitch = 1.0f;
    ad->roll = 1.1f;
    ad->yaw = 1.2f;
}

int main(void)
{
    accel_data_t accelData;
    gyro_data_t gyroData;

    while(1)
    {
        readGyro(&gyroData);
        readAccel(&accelData);

        cout << "AccelPitch=" << accelData.pitch << endl;
        cout << "AccelRoll=" << accelData.roll << endl;
        cout << "AccelYaw=" << accelData.yaw << endl;
        cout << "GyroPitch=" << gyroData.pitch << endl;
        cout << "GyroRoll=" << gyroData.roll << endl;
        cout << "GyroYaw=" << gyroData.yaw << endl;
    }
}

请注意,这也比您的示例更具可读性,因为它明确命名了每个变量,而不是将它们表示为 returned 值的偏移量。不再需要分配给新变量来让您理解值的含义。

这两个结构实际上是相同的,因此如果需要可以将其压缩为一个通用结构。

C++ 的内置数组是从 C 继承而来的,不一定像大多数人期望的那样工作。假设您有这样的功能:

float* get_vec() {
    float vec[3] = { 1.0f, 2.0f, 3.0f };
    return vec;
}

这实际上做的是return堆栈分配变量vec地址;不幸的是 vec 将在函数结束时超出范围,并且 returned 地址将毫无意义。

解决方法是将数组包装在 struct 中, 可以 按值 return 编辑。您可以定义自己的,也可以使用 C++ 标准库中的 std::array,如下所示:

std::array<float, 3> get_vec() {
    std::array<float, 3> vec = { 1.0f, 2.0f, 3.0f };
    return vec;
}

您正在做的是返回数组的 地址,该数组是函数的本地数组,该数组在函数退出时被销毁。

如果出于索引原因需要数组,那么我建议使用 std::array

std::array<float, 3> readGyro() {
    /*get data from sensor here*/
    return {gyroPitch, gyroRoll, gyroYaw};
}

但最好使用这样的 struct

struct angles
{
    float pitch;
    float roll;
    float yaw;
};

angles readGyro() {
    /*get data from sensor here*/
    return {gyroPitch, gyroRoll, gyroYaw};
}

按值

将数组作为结构包装到return

在复制数组作为数据成员时,数组元素将被一个一个地复制,而不是复制衰减的指针。这避免了 returning 局部变量的地址。

struct float3{
    float fs[3];
};

float3 readGyro(){
    float3 f3 = {};
    f3.fs[0] = gyroPitch;
    f3.fs[1] = gyroRoll;
    f3.fs[2] = gyroYaw;
    return f3;
}

但是像其他答案所说的那样使用std::array<float, 3>是非常合适的。你不需要再发明一个轮子。

通过引用传递得到结果

如果您喜欢通过参数获取结果,请使用引用而不是指针以避免丢失大小信息(退化为指针)。这也确保只传递类型 float[3]

void readGyro(float (&fs)[3])
{        
    fs[0] = gyroPitch;
    fs[1] = gyroRoll;
    fs[2] = gyroYaw;
}