【问题标题】:Why can't I eliminate this temporary variable in Eigen3?为什么我不能在 Eigen3 中消除这个临时变量?
【发布时间】:2023-03-29 10:03:01
【问题描述】:

我遇到了矩阵乘向量乘法的问题。即看起来无害的表达式总是返回接近 [1 0] 的向量,而看起来相似的表达式返回正确的结果:

// version WITH temp var, correct
Eigen::Vector3d lcoord_eig(lcoord[0], lcoord[1], lcoord[2]);
auto lcoord2d = P3to2 * lcoord_eig;
std::cout << std::endl << lcoord2d << std::endl;

// version WITHOUT temp var, always [1 0]
auto lcoord2d_2 = P3to2 * Eigen::Vector3d(lcoord[0], lcoord[1], lcoord[2]);
std::cout << std::endl << lcoord2d_2 << std::endl;

其中P3to2 是一个 2×3 矩阵 (Eigen::MatrixXd),lcoord 是某个其他库的 3d 向量类型,上面的代码包含在一个 for 循环中。

一些输出(我的注释):

-0.0036135
2.1684e-18   // correct

1
0   // [1 0], wrong

0.00209583
0.000388139   // correct

1
5.55112e-17   // [1 0], wrong

0.00148429
-0.000435008   // correct

1
5.55112e-17   // [1 0], wrong

我花了很长时间才发现这个错误,但我仍然不明白发生了什么会导致第二个版本的行为如此。我犯了什么错误?


编辑:这也发生在常量向量上,比如Eigen::Vector3d(.5,.5,.5)

【问题讨论】:

标签: c++ eigen eigen3


【解决方案1】:

我的猜测(鉴于您没有在问题中包含足够的信息以供任何人重现)是 auto 的使用是您的问题。在您的第二种情况下,即不工作的情况下,我怀疑您留下了对已破坏的临时 Vector3D 的悬空引用。

documentations 说“不要在 Eigen 表达式中使用 auto 关键字,除非你 100% 确定自己在做什么”。

如果您使用显式类型,您的程序会更清晰,更有可能运行。

【讨论】:

  • 你是对的,用Eigen::Vector2d 替换auto 解决了这个问题。我不知道auto 会这么危险!
  • @xjcl 我猜 Eigen 使用表达式模板,这就是原因
  • @Sopel 是的,Eigen 确实使用了表达式模板,这可能会在内部将临时绑定到 const 引用,并且该绑定在语句结束时不再有效。如果要强制求值,请在表达式末尾使用.eval();,例如auto lcoord2d = (P3to2 * lcoord_eig).eval();。参见例如this link 了解更多详情。
猜你喜欢
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
相关资源
最近更新 更多