[踩坑] Eigen 惰性求值与生命周期
引入
做作业时遇到个诡异的问题:
1 | |
按照上面的写法,是正常运行的,而按照注释的写法,得到的就是非常大的数字,明显是不正确的。这两种方法看上去区别不是很大,那么问题出在哪里呢?
分析
看一下相关的定义:
1 | |
似乎是没什么问题,flatten(grad_g) 的值被 const MatrixBase<Rhs>& 常值引用,在 solve 函数内是不会失效的。于是继续深入。
1 | |
其中 m_dec 和 m_rhs 都是引用。
到这里,flatten(grad_g) 的值还是没有失效的,但我们可以看到,solve 函数实际上并没有进行求解,只是构造了一个 Solve 对象。这是 Eigen 的懒惰求值特性,由于用了 auto 变量接受返回值,所以得到的还是 Solve 对象,这点在 IDE 的提示中也可以看到。
当后面使用 delta_X_flatten 的时候,由于它是一个引用了 flatten(grad_g) 临时对象的 Solve 对象,而 flatten(grad_g) 已经被析构了,便会造成悬垂引用,产生错误。
解决
解决方法有两个,一个是像上面一样,先把 flatten(grad_g) 赋值给 grad_g_flatten,grad_g_flatten 的生命周期足够长,就不会悬垂引用了;另一个是指明 delta_X_flatten 的类型为 MatrixXd,这样在赋值的时候,就会触发求值,后面不再依赖这个临时变量,也就不会悬垂引用了。
[踩坑] Eigen 惰性求值与生命周期
http://xiao-h.com/2025/02/19/踩坑-Eigen惰性求值与生命周期/