本文整理自 SLAM / 机器人项目中对 KalmanFilter 构造函数的讨论,涵盖构造函数语法、传参方式、初始化列表、const 引用等核心 C++ 知识点。
一、问题代码
在 Eigen 库(MatrixXd 动态矩阵)背景下,常见的卡尔曼滤波类构造函数写法如下:
class KalmanFilter {
public:
// 构造函数:初始化
KalmanFilter(const MatrixXd& A_, const MatrixXd& B_,
const MatrixXd& H_, const MatrixXd& Q_,
const MatrixXd& R_)
: A(A_), B(B_), H(H_), Q(Q_), R(R_) {}
};
这段代码拆成上半部分(参数)和下半部分(初始化列表),各自有讲究。
二、上半部分:参数 const MatrixXd&
KalmanFilter(const MatrixXd& A_, const MatrixXd& B_, ...)
这是传参方式:const + 引用(&) 的组合。
1. 引用 & —— 为了性能
MatrixXd 是矩阵,可能包含大量数据(如 100×100)。如果只写 MatrixXd A_(按值传递),C++ 会在调用时拷贝一整份矩阵,极其消耗内存和时间。
加上 & 变成引用,相当于只传矩阵的"地址",零拷贝开销。
2. const —— 为了安全
既然只传了地址(引用),构造函数内部就有可能意外修改外部的原始矩阵。加上 const 就是向编译器和程序员承诺:
“我只在构造函数里读这些矩阵的值,绝不修改它们。”
一句话:const T& 是 C++ 中传递大对象的黄金法则——既避免拷贝,又保证只读。
三、下半部分:初始化列表 : A(A_), …
: A(A_), B(B_), H(H_), Q(Q_), R(R_)
冒号 : 后面的部分叫做成员初始化列表。
为什么要这么写?(而不是在 {} 里赋值)
① 性能更高
如果在构造函数大括号 {} 里写 this->A = A_;,这叫赋值。对于类类型成员(如矩阵),会导致:
而用初始化列表,矩阵会直接调用拷贝构造函数一步到位,只有一次开销。
② 某些成员必须这么写
如果类里有 const 常量成员或引用成员,它们必须在对象创建的那一瞬间就绑定初始值,不能在 {} 里再赋值。用初始化列表是唯一选择。
③ 大括号 {} 为空
说明这个构造函数只需要完成初始化,不需要执行其他复杂逻辑(如打印日志、开线程等),所以函数体留空。
四、大白话理解:这个构造函数在做什么?
卡尔曼滤波算法需要几个固定的核心矩阵:
| A | 状态转移矩阵 |
| B | 控制输入矩阵 |
| H | 观测矩阵 |
| Q | 过程噪声协方差 |
| R | 观测噪声协方差 |
这段代码的意思是:
“在创建卡尔曼滤波器对象时,请把这 5 个矩阵原封不动(不拷贝、不修改)地借给我,我用它们来初始化我内部的成员变量,搞定后构造函数就完工了。”
五、知识延伸:const 引用参数的通用法则
const T& 不仅用于构造函数,而是 C++ 中传递任何大对象的通用规范:
// 只读大对象 → 用 const 引用
void process(const MatrixXd& data);
// 需要修改对象 → 用普通引用(不加 const)
void modify(MatrixXd& data);
// 小对象(int、double、指针)→ 直接按值传递即可,无需引用
void setCount(int count);
核心原则:
- 对象较大(矩阵、容器、自定义类)→ const T&
- 对象很小(内置类型)→ T
- 需要修改传入对象 → T&(去掉 const)
六、总结
| const T& | 只读引用,避免拷贝 + 保证安全 |
| 初始化列表 : x(y) | 高效初始化成员,一步到位 |
| 空函数体 {} | 构造函数只需初始化,无额外逻辑 |
| 命名约定 A_ | 参数名加下划线后缀,与成员 A 区分 |
掌握这套写法,不仅 KalmanFilter,任何 C++ 类的构造函数都能写得规范、高效、安全。
网硕互联帮助中心



评论前必须登录!
注册