从模板函数返回的特征矩阵改变值
Returned Eigen Matrix from templated function changes value
我遇到了一些关于特征库和模板函数的奇怪行为。
也许有人可以向我解释,为什么第一个版本不起作用,而其他 3 个可以。我的猜测是释放一些局部变量的第一种情况,但希望有人能启发我。提前致谢。
代码如下:
编译器-资源管理器:https://compiler-explorer.com/z/r45xzE417
#include <concepts>
#include <iostream>
#include <Eigen/Core>
auto RungeKutta1_auto(const auto& f, const std::floating_point auto& h, const auto& y_n)
{
auto ret = y_n + h * f(y_n);
std::cout << ret.transpose() << std::endl;
return ret;
}
template<typename _Scalar, int _Rows, int _Cols>
auto RungeKutta1_template(const auto& f, const std::floating_point auto& h, const Eigen::Matrix<_Scalar, _Rows, _Cols>& y_n)
{
Eigen::Matrix<_Scalar, _Rows, _Cols> ret = y_n + h * f(y_n);
std::cout << ret.transpose() << std::endl;
return ret;
}
int main()
{
auto f = [](const Eigen::Matrix<double, 10, 1>& y) {
Eigen::Matrix<double, 10, 1> y_dot = 2 * y;
return y_dot;
};
auto g = [](const Eigen::Matrix<double, 10, 1>& y) {
return 2 * y;
};
std::cout << "RungeKutta1_auto(f, 0.05, y):" << std::endl;
Eigen::Matrix<double, 10, 1> y;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_auto(f, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 3.47627e-311 1 2 3 4 5 6.6 7 8 9
std::cout << "RungeKutta1_template(f, 0.05, y):" << std::endl;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_template(f, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
std::cout << "RungeKutta1_auto(g, 0.05, y):" << std::endl;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_auto(g, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
std::cout << "RungeKutta1_template(g, 0.05, y):" << std::endl;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_template(g, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
}
在第一个版本中,
auto ret = y_n + h * f(y_n);
由于 Eigen 的表达式模板,这为您提供了一个中间表达式类型,而不是 Matrix
类型。您需要在其上显式调用 eval()
以强制进行延迟评估(并将表达式转换为生成的 Matrix
类型对象);例如:
auto ret = (y_n + h * f(y_n)).eval();
在其他版本中,您将 ret
的类型明确键入为 Matrix
类型,这意味着您最终不会存储中间表达式模板类型。
我遇到了一些关于特征库和模板函数的奇怪行为。
也许有人可以向我解释,为什么第一个版本不起作用,而其他 3 个可以。我的猜测是释放一些局部变量的第一种情况,但希望有人能启发我。提前致谢。
代码如下:
编译器-资源管理器:https://compiler-explorer.com/z/r45xzE417
#include <concepts>
#include <iostream>
#include <Eigen/Core>
auto RungeKutta1_auto(const auto& f, const std::floating_point auto& h, const auto& y_n)
{
auto ret = y_n + h * f(y_n);
std::cout << ret.transpose() << std::endl;
return ret;
}
template<typename _Scalar, int _Rows, int _Cols>
auto RungeKutta1_template(const auto& f, const std::floating_point auto& h, const Eigen::Matrix<_Scalar, _Rows, _Cols>& y_n)
{
Eigen::Matrix<_Scalar, _Rows, _Cols> ret = y_n + h * f(y_n);
std::cout << ret.transpose() << std::endl;
return ret;
}
int main()
{
auto f = [](const Eigen::Matrix<double, 10, 1>& y) {
Eigen::Matrix<double, 10, 1> y_dot = 2 * y;
return y_dot;
};
auto g = [](const Eigen::Matrix<double, 10, 1>& y) {
return 2 * y;
};
std::cout << "RungeKutta1_auto(f, 0.05, y):" << std::endl;
Eigen::Matrix<double, 10, 1> y;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_auto(f, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 3.47627e-311 1 2 3 4 5 6.6 7 8 9
std::cout << "RungeKutta1_template(f, 0.05, y):" << std::endl;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_template(f, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
std::cout << "RungeKutta1_auto(g, 0.05, y):" << std::endl;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_auto(g, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
std::cout << "RungeKutta1_template(g, 0.05, y):" << std::endl;
y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
y = RungeKutta1_template(g, 0.05, y);
std::cout << y.transpose() << std::endl;
// Output
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
// 0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
}
在第一个版本中,
auto ret = y_n + h * f(y_n);
由于 Eigen 的表达式模板,这为您提供了一个中间表达式类型,而不是 Matrix
类型。您需要在其上显式调用 eval()
以强制进行延迟评估(并将表达式转换为生成的 Matrix
类型对象);例如:
auto ret = (y_n + h * f(y_n)).eval();
在其他版本中,您将 ret
的类型明确键入为 Matrix
类型,这意味着您最终不会存储中间表达式模板类型。