c++ - 将按值返回向量的函数作为 ublas::element_prod() 的参数传递有什么问题?
问题描述
我似乎无法理解为什么直接将函数作为参数传递给 ublas::element_prod() 会产生错误的结果。
如果我运行以下代码:
#include <cmath>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace ublas = boost::numeric::ublas;
ublas::vector<double>
vector_ln(ublas::vector<double> x) {
for(auto it = x.begin(); it != x.end(); ++it) {
(*it) = log(*it);
}
return x;
}
int main(void) {
ublas::vector<double> x(2, 2.0);
ublas::vector<double> y(2, 10.0);
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
auto tmp = vector_ln(y);
auto ret1 = ublas::element_prod(
x,
tmp);
std::cout << ret1 << std::endl;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
auto ret2 = ublas::element_prod(
x,
vector_ln(y));
std::cout << ret2 << std::endl;
}
我得到以下输出:
x = [2](2,2)
y = [2](10,10)
[2](4.60517,4.60517)
x = [2](2,2)
y = [2](10,10)
[2](0,4.60517)
谁能告诉我为什么第二种编码风格会产生错误的结果,而没有编译错误?
解决方案
问题是 ublas 使用表达式模板,其中许多操作的结果是临时的,它只是保留对其输入的指针/引用,并在分配给变量时进行评估。这样做是为了减少不必要的计算和复制。见https://en.wikipedia.org/wiki/Expression_templates
但是,随着 C++11 的引入,使用 会产生危险的交互auto
,因为这会保存表达式模板的副本,而不是结果。此表达式模板具有对 的临时返回的悬空引用vector_ln(y)
,并导致您看到的问题。
由于主要问题是与 auto 的交互,因此解决方案是将其保存到正确的 ublas 矩阵类型作为 element_prod() 的结果。它仅在第一种情况下有效,因为存储的引用都不是临时的。
推荐阅读
- javascript - 咖喱函数失去对象上下文
- c++ - 应该通过移动“接管”另一个对象的所有权的类不起作用
- android - ActivityMainBinding 未解决和同步错误
- django - 尝试向表单字段的标签添加链接时,__init __ () 出现意外的关键字参数“初始”错误
- java - Keycloak Kerberos 阻止登录对话框
- flutter - dart-define 参数不适用于构建
- c++ - 使用 MSYS2/MINGW-64 缺少 POSIX 和 std 符号
- javascript - 如何防止用户更改ajax调用中的重要数据?
- python - Rasa Bot 按钮单击不响应
- azure-devops - 具有多个工件和阶段的 Azure DevOps 发布管道