从 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 将指针指向 readGyro
和 readAccel
的堆栈。当这些函数退出时,堆栈的那部分将被回收,您将留下未定义的行为。
一种方法是分配数组并 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;
}
美好的一天 :) 我正在编写一个代码,用于从加速度计和陀螺仪获取俯仰角、偏航角和滚动角。为了创建一个看起来更简洁、易于理解的代码,我求助于创建两个不同的函数。一个用于计算 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 将指针指向 readGyro
和 readAccel
的堆栈。当这些函数退出时,堆栈的那部分将被回收,您将留下未定义的行为。
一种方法是分配数组并 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;
}