以下代码在 cl.exe 中运行良好(产生预期输出 2, 9.9)。
对于 g++,使用 -O3 优化时根本不会产生任何输出,而使用 -O1 和 -O2 优化时会产生错误的输出 (1,10)。
g++ 的版本是 12.2.0,从 Windows 10 中的命令窗口运行。
我对 auto 和 valarray 有错误的期望,还是我只是做了一些愚蠢的事情?
#include <iostream>
#include <valarray>
int main()
{
double dx = 0.1;
std::valarray<double> Y{ 1.0, 10.0 };
// Works fine with g++, all optimisation levels
// std::valarray<double> dY1 = dx * std::valarray<double>{ Y[1], -Y[0] };
// Y += dY1;
// Fails completely with g++ -O3; gives wrong answer with -O1 and -O2; works fine with cl.exe
auto dY2 = dx * std::valarray<double>{ Y[1], -Y[0] };
Y += dY2;
std::cout << Y[0] << '\t' << Y[1] << '\n';
}
libstdc++ 使用表达式模板来实现 valarray 操作。
这样就
X = 3 * Y + 2
可以将类似的事情实现为单个循环,而不是一个循环乘以 3,然后另一个循环加 2。但是,这些表达式模板存储对其操作数的引用。Your
std::valarray<double>{ Y[1], -Y[0] }
是临时的,因此它立即成为悬空引用。复制到实数
std::valarray<double>
实际上会在临时死亡之前评估表达式模板。您还可以看到,如果您不使用临时文件,这也是可行的: