C++ Armadillo:使用迭代器的双循环
C++ Armadillo: double for loop using iterators
在双 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);
}
}
使用迭代器而不是整数索引。感谢您的任何建议。
我想到了三件事,不仅是双倍迭代,还有任何类型的迭代(只需将以下所有内容应用两次...)
1) 如果容器的内容在循环过程中没有改变,调用一次end()并保存它,并在循环的每次迭代中将迭代器与保存的值进行比较。
不太好:
for(arma::vec::iterator i = test.begin(); i != test.end(); ++i)
正如所写,end() 在每个循环的迭代中在技术上被调用,并且它的 return 值正在与循环迭代器的当前值进行比较。
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 迭代语法准确地告诉编译器正在发生什么,为编译器提供最佳机会来使用它被编程为知道的所有容器迭代技巧。
建议在访问矩阵中的元素时仍然使用单循环。 Armadillo 以 column-major 格式存储数据(为了与 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() and .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; } );
在双 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);
}
}
使用迭代器而不是整数索引。感谢您的任何建议。
我想到了三件事,不仅是双倍迭代,还有任何类型的迭代(只需将以下所有内容应用两次...)
1) 如果容器的内容在循环过程中没有改变,调用一次end()并保存它,并在循环的每次迭代中将迭代器与保存的值进行比较。
不太好:
for(arma::vec::iterator i = test.begin(); i != test.end(); ++i)
正如所写,end() 在每个循环的迭代中在技术上被调用,并且它的 return 值正在与循环迭代器的当前值进行比较。
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 迭代语法准确地告诉编译器正在发生什么,为编译器提供最佳机会来使用它被编程为知道的所有容器迭代技巧。
建议在访问矩阵中的元素时仍然使用单循环。 Armadillo 以 column-major 格式存储数据(为了与 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() and .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; } );