C++中使用Eigen库初始化动态向量并正确调用的方法
问题原因分析
你将相关变量收拢到结构体中、放在头文件统一管理的思路是可行的,出现type identifier expected报错是因为违反了C++类/结构体的成员声明语法规则:
在结构体内部直接声明成员时,类型 成员名(参数)的格式会被编译器解析为成员函数声明。你写的std::vector<std::vector<float>> posDesired(6)会被判定为:声明一个名为posDesired、返回值为二维float向量、入参类型为6的函数,但6不是合法的类型标识符,因此触发报错。
另外你的代码还有两个可优化点:
- 头文件中使用
using namespace Eigen;会造成命名空间污染,所有引入该头文件的源文件都会被强制注入Eigen命名空间,提升命名冲突风险,不建议这么写。 - 既然使用Eigen做数值开发,固定维度的线性代数结构优先用Eigen原生类型,比嵌套
std::vector内存连续性更好、运算效率更高,也更适配Eigen的工具函数。
修正方案
方案1:保留嵌套std::vector结构(仅修正语法错误)
最稳妥的写法是为结构体定义构造函数,在构造函数的初始化列表中完成成员的初始化,完全避免语法歧义,代码如下:
#pragma once #ifndef INIT_VARIABLES_H #define INIT_VARIABLES_H #include <vector> #include "Eigen/Dense" struct DataStruct { std::vector<std::vector<float>> posDesired; std::vector<std::vector<float>> velDesired; std::vector<std::vector<float>> posRobot; std::vector<std::vector<float>> ErrorRobot; std::vector<std::vector<float>> velRobot; std::vector<std::vector<float>> velRobotcalc; std::vector<std::vector<float>> errorPos; std::vector<std::vector<float>> errorVel; std::vector<float> errorAnt; std::vector<std::vector<float>> P; std::vector<std::vector<float>> D; std::vector<std::vector<float>> I; std::vector<std::vector<float>> PIDOUT; std::vector<float> errorInt; std::vector<float> posRobotAnt; // 构造函数初始化所有成员 DataStruct() : posDesired(6), velDesired(6), posRobot(6), ErrorRobot(6), velRobot(6), velRobotcalc(6), errorPos(6), errorVel(6), errorAnt(6, 0.0f), P(6), D(6), I(6), PIDOUT(6), errorInt(6, 0.0f), posRobotAnt(6, 0.0f) {} }; #endif
使用时在源文件中引入头文件,实例化结构体即可,需要调整第二维长度时直接对对应外层vector的元素做resize/push_back操作即可。
方案2:使用Eigen原生类型(推荐,适配你的开发场景)
你需要的“第一维固定为6、第二维动态调整为i”的结构,刚好对应Eigen的固定行、动态列矩阵类型Eigen::Matrix<float, 6, Eigen::Dynamic>,相比嵌套vector性能更好,操作更便捷,修正后代码如下:
#pragma once #ifndef INIT_VARIABLES_H #define INIT_VARIABLES_H #include "Eigen/Dense" struct DataStruct { // 6行、动态列float矩阵,对应6*i维度 Eigen::Matrix<float, 6, Eigen::Dynamic> posDesired; Eigen::Matrix<float, 6, Eigen::Dynamic> velDesired; Eigen::Matrix<float, 6, Eigen::Dynamic> posRobot; Eigen::Matrix<float, 6, Eigen::Dynamic> ErrorRobot; Eigen::Matrix<float, 6, Eigen::Dynamic> velRobot; Eigen::Matrix<float, 6, Eigen::Dynamic> velRobotcalc; Eigen::Matrix<float, 6, Eigen::Dynamic> errorPos; Eigen::Matrix<float, 6, Eigen::Dynamic> errorVel; Eigen::Matrix<float, 6, 1> errorAnt; // 固定6*1列向量 Eigen::Matrix<float, 6, Eigen::Dynamic> P; Eigen::Matrix<float, 6, Eigen::Dynamic> D; Eigen::Matrix<float, 6, Eigen::Dynamic> I; Eigen::Matrix<float, 6, Eigen::Dynamic> PIDOUT; Eigen::Matrix<float, 6, 1> errorInt; Eigen::Matrix<float, 6, 1> posRobotAnt; DataStruct() { // 固定尺寸向量初始化为全0 errorAnt.setZero(); errorInt.setZero(); posRobotAnt.setZero(); // 动态尺寸矩阵初始化为6行0列,后续需要时调用resize调整列数 posDesired.resize(6, 0); velDesired.resize(6, 0); posRobot.resize(6, 0); ErrorRobot.resize(6, 0); velRobot.resize(6, 0); velRobotcalc.resize(6, 0); errorPos.resize(6, 0); errorVel.resize(6, 0); P.resize(6, 0); D.resize(6, 0); I.resize(6, 0); PIDOUT.resize(6, 0); } }; #endif
调用示例:
#include "init_variables.h" int main() { DataStruct data; int i = 5; // 调整为6*5维度 data.posDesired.resize(6, i); // 访问第0行第0列元素 data.posDesired(0, 0) = 1.2f; return 0; }
注意事项
- 不要在头文件中直接定义全局的结构体实例,否则多源文件包含时会触发重复定义错误。如果需要全局可用的实例,可在头文件中用
extern DataStruct g_data;声明,在单个cpp文件中写入DataStruct g_data;完成定义。 - C++11及以上标准虽然支持成员就地初始化,但不要用圆括号传参,否则仍会被解析为函数声明;如果要用就地初始化,可使用花括号,但要注意区分列表初始化和构造函数调用的歧义,优先选择构造函数初始化列表的写法。
内容的提问来源于stack exchange,提问作者mikel lasa
相关产品推荐
相关产品推荐

