Eigen::CwiseBinaryOp变量意外修改无关变量值问题求助
问题原因分析
核心原因:auto保存了Eigen延迟计算的表达式对象,导致悬垂引用
Eigen为了优化性能,大部分算术运算(比如标量乘法)不会立即计算结果,而是返回一个延迟计算的表达式对象(比如这里的CwiseBinaryOp),这个对象仅保存运算的操作数引用和运算逻辑,直到需要实际取值时才执行计算。
当你用auto a = Vector3d(1,2,3)*0.1;时:
Vector3d(1,2,3)是临时对象,这条语句执行完毕后,该临时对象会被销毁;auto推导的类型是表达式对象(而非Vector3d),它持有对上述临时对象的引用;- 后续访问
a时,引用的是已经被销毁的内存,这属于未定义行为。
跨平台表现差异的原因
未定义行为的结果完全依赖编译器和运行环境:
- Win10环境下,销毁的临时对象内存未被立即覆盖,所以访问
a时碰巧拿到了原来的数值; - Ubuntu环境下,后续创建
Vector3d(-10,-9,-8)临时对象时,复用了之前临时对象的内存空间,表达式对象引用的内存被新数据覆盖,此时计算a的取值时,就会用新的操作数(-10,-9,-8)执行原来的乘0.1运算,最终得到-1,-0.9,-0.8。
解决方案
有两种方式可以避免这个问题:
- 显式指定变量类型:直接声明
a和b为Vector3d,触发表达式立即计算,将结果存储到实际的向量对象中:Vector3d a = Vector3d(1,2,3)*0.1; Vector3d b = Vector3d(-10,-9,-8)*100.0; - 强制计算表达式:调用
.eval()方法,让Eigen立即计算运算结果并返回实际的向量对象:auto a = (Vector3d(1,2,3)*0.1).eval(); auto b = (Vector3d(-10,-9,-8)*100.0).eval();
内容的提问来源于stack exchange,提问作者Tom Willow
相关产品推荐
相关产品推荐

