我对将矩阵的子视图传递给其他对象(或函数)感兴趣,以便该对象/函数可以修改列/矩阵的已定义段。
我目前正在使用armadillo库,并且可以获取和使用对单个矩阵条目的引用(f
下面的函数)。我正在寻找一种有效的方法来传递对子视图的引用。我认为h
下面的函数代码可以实现此目标,但是我不确定。我的主要问题是:假设我想将一个引用存储在一个类中(而不仅仅是在函数中使用h
),是否可以改进h
下面的函数?
三个不太重要的跟进问题是:1)在编写接受arma :: Col参数类型的函数而不是指定子视图时是否可以完成此操作?2)如果没有,是否还有另一个C ++矩阵库将允许这种事情而无需明确地涉及子视图?(我查看了Eigen及其.blocks语法,但我认为问题是相同的);和3)我对传递给函数的引用g
在表达式完成后消失了吗?
#include <iostream>
#include <armadillo>
void f(double & x) { x = 5.33392;}
void g(arma::subview_col<double> && x, double y) { x(0) = y; }
void h(arma::subview_col<double> x, double y) { x(0) = y; }
int main () {
arma::Mat<double> A = arma::randu<arma::Mat<double> >(3,3);
A(1,1) = 3;
A.submat(0,0,1,1) = arma::zeros<arma::Mat<double> >(2,2);
std::cout << A << std::endl;
double & k = A(1,1);
std::cout << k << std::endl;
f(k); // THis is ok, works.
g(A.col(2), 153.0); // It compiles and the value changes...
// A.col(2) gets destroyed when the above expression is done
// evaluating... so not a reference one can keep around.
std::cout << A << std::endl;
// Here the subview is passed by value, and it keeps its reference to
h(A.col(1), 153.0);
std::cout << A << std::endl;
return 0;
}
为我编译:
g++ -o submatrix_views -std=c++11 ./submatrix_views.cpp
我还没有用过犰狳,所以我不是最适合回答的问题,但是我认为这是一个更一般的C ++问题,此外,还没有答案:-)
所以:
假设我想将引用存储在类中(不仅像在h中那样在函数中使用),有没有办法改善下面的函数h?
我认为您混淆了一些与矩阵和视图无关的C ++基本概念。引用本质上指向一个对象,因此您应该首先担心存储对象本身,然后是引用。
存在对对象的引用这一事实可能是将对象的生存期延长到引用的生存期的原因,但这并非总是如此。有关某些解释和规则,请参见我先前的问题之一的答案。
因此,确定的最佳方法是首先存储对象。我敢打赌A.col(1)
,A.submat(0,0,1,1)
它们是临时对象,您可以通过以下任何一种方式将它们存储在变量中:
arma::subview_col<double> col = A.col(1);
decltype(A.col(1)) col = A.col(1);
auto col = A.col(1);
如果知道类型,则可以只使用一个这样的变量作为类的成员(如果不知道,请使用decltype
)。我不知道犰狳的详细信息,但是我敢打赌,它所A.col(1)
包含的不仅仅是引用A
和size_t
value的整数(我想是)1
。它是一个轻量级的对象,旨在充当一种通用的引用。不要害怕存储它。只是练习,尝试
auto col = A.col(2);
col = 153.0;
任何人都看到它与A.col(2) = 153.0;
或相同g(A.col(2), 153.0);
。在这一点上,没有什么可以阻止您将其存储col
在任何地方以备后用。
将视图存储在某个地方,然后需要将其传递给函数。如果该视图仅用于读取,请编写以下两个重载:
void read( arma::subview_col<double> && x, double& y) { y = x(0); }
void read(const arma::subview_col<double> & x, double& y) { y = x(0); }
如果它也用于书写,则:
void write(arma::subview_col<double> && x, double y) { x(0) = y; }
void write(arma::subview_col<double> & x, double y) { x(0) = y; }
我推荐的通用解决方案如下:
template <typename X> void read (X&& x, double& y) { y = std::forward<X>(x)(0); }
template <typename X> void write(X&& x, double y) { std::forward<X>(x)(0) = y; }
或者,甚至更通用:
template <typename X, typename Y>
void read (X&& x, Y&& y) { std::forward<Y>(y) = std::forward<X>(x)(0); }
template <typename X, typename Y>
void write(X&& x, Y&& y) { std::forward<X>(x)(0) = std::forward<Y>(y); }
现在X
并且Y
可以是任何东西,或更确切地说,可以X
是任何类型的数组或视图,并且Y
是与元素类型兼容(可转换为或从转换为)的任何类型X
。如果不是,编译器将对其进行诊断。如果armadillo支持,您甚至可以拥有一个数组Y
和一个数组(或视图)X
。
另外,您可以泛化为n元函数,而不必担心无限const
/非const
重载组合。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句