Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将对子矩阵视图的持久引用作为函数参数传递?_C++_Matrix_Armadillo - Fatal编程技术网

C++ 如何将对子矩阵视图的持久引用作为函数参数传递?

C++ 如何将对子矩阵视图的持久引用作为函数参数传递?,c++,matrix,armadillo,C++,Matrix,Armadillo,我感兴趣的是将矩阵的子视图传递给其他对象(或函数),以便对象/函数可以修改列/矩阵的定义段 我目前正在使用armadillo库,我可以获得并使用对单个矩阵项的引用(下面的函数f)。我正在寻找一种有效的方法来传递对子视图的引用。我认为下面函数h的代码实现了这个目标,但我不确定。我的主要问题是:假设我想在类中存储一个引用(而不仅仅是在h中的函数中使用),有没有办法改进下面的函数h 三个不太重要的后续问题是:1)在编写函数以接受arma::Col类型的参数而不是指定子视图时,是否可以实现这一点?2)如

我感兴趣的是将矩阵的子视图传递给其他对象(或函数),以便对象/函数可以修改列/矩阵的定义段

我目前正在使用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;
}

<>我没有使用犰狳,所以我不是最合适的回答,但我认为这是一个更一般的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);
任何情况下,它与
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 read(arma::subview_col&&x,double&y){y=x(0);}
void read(const arma::subview_col&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; }
void write(arma::subview_col&&x,double y){x(0)=y;}
void write(arma::subview_col&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 void read(X&&X,double&y){y=std::forward(X)(0);}
模板无效写入(X&&X,双y){std::forward(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&&X,Y&&Y){std::forward(Y)=std::forward(X)(0);}
模板
无效写入(X&&X,Y&&Y){std::forward(X)(0)=std::forward(Y);}
现在
X
Y
可以是任何类型,或者更准确地说,
X
是任何类型的数组或视图,
Y
是与
X
的元素类型兼容(可转换为/从中转换)的任何类型。如果不是,编译器将对其进行诊断。如果犰狳支持的话,你甚至可以有一个数组
Y
和一个数组(或视图)的数组
X


另外,您可以推广到n元函数,而不必担心无限
const
/non-
const
重载组合。

我确实认识到您提到的对象生命周期问题,但我仍然认为这里不能保证存储我们制作的Armadillo子视图副本不会过时。不过,犰狳似乎确实竭尽全力让用户控制复制,所以这应该是安全的。。。(你的解释比我所接受的问题要详细得多,谢谢!)@Krzysztof如果犰狳视图确实包含对原始阵列的引用,那么只有在原始阵列被破坏(例如超出范围)时,它才会过时(悬挂)。因此,您只需要担心原始阵列的存储。我确信这在文件中的某个地方;否则,不要害怕看代码。@Krzysztof我所描述的
auto col=A.col(2)不一定是视图的副本;它可以通过移动原始视图来构建,即使犰狳视图不可复制(但至少可以移动),也可以通过移动来构建。然后,它就像保持原始视图,而不仅仅是显示子表达式
A.col(2)
的完整表达式,即用于封闭范围。
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); }