C++Armadillo:使用迭代器的双循环



在double for循环中使用迭代器的最佳方式是什么。对于单个循环,显而易见的方式似乎是:

arma::vec test = arma::ones(10);
for(arma::vec::iterator i = test.begin(); i != test.end(); ++i){
   int one = *i;
}

所以我想转换以下内容:

arma::mat test = arma::ones(10,10);
for (int i = 0; i < test.n_rows; i++){
 for (int j = 0; j < test.n_cols; j++){
  int one = test(i,j);
 }
}

使用迭代器而不是整数索引。谢谢你的建议。

访问矩阵中的元素时,建议仍使用单个循环。Armadillo以列主格式存储数据(为了与LAPACK兼容),因此迭代器将沿着矩阵中的每一列移动。

arma::mat A(4, 5, arma::fill::randu);
A.print("A:");
// C++98 
arma::mat::iterator it_end = A.end();
for(arma::mat::iterator it = A.begin(); it != it_end; ++it)
   {
   std::cout << (*it) << std::endl;
   }
// C++11
for(const auto& val : A)
   {
   std::cout << val << std::endl;
   }

如果您真的想使用双循环,请使用.begin.col()和.end_col():

// C++11
for(arma::uword c=0; c < A.n_cols; ++c)
  {
  auto it_end = A.end_col(c);
  for(auto it = A.begin_col(c); it != it_end; ++it)
    {
    std::cout << (*it) << std::endl;
    }
  }

最后,.for_each()函数是使用迭代器的替代方法:

 // C++11
 A.for_each( [](arma::mat::elem_type& val) { std::cout << val << std::endl; } );

脑海中浮现出三件事,不仅是两次迭代,而且是任何类型的迭代(只需应用以下所有内容两次…)

1) 如果容器的内容在循环过程中没有改变,请调用end()一次并保存它,并在循环的每次迭代中将迭代器与保存的值进行比较。

不太好:

for(arma::vec::iterator i = test.begin(); i != test.end(); ++i)

正如所写的,从技术上讲,在每个循环的迭代中都会调用end(),并将其返回值与循环迭代器的当前值进行比较。

2)

更好:

const arma::vec::iterator e=test.end();
for(arma::vec::iterator i = test.begin(); i != e; ++i)

这有更好的机会得到优化,尤其是使用const限定符(尽管编译器可能能够自己计算出来,如果e从未被修改的话)。

3)

最佳:

for(const auto &value:test)

C++11迭代语法告诉编译器到底发生了什么,为编译器提供了最好的机会来使用它编程要了解的所有容器迭代技巧。

最新更新