push_back / append或在C ++ Armadillo中追加带循环的向量

时间:2015-01-31 02:20:44

标签: c++ armadillo

我想创建一个整数的向量(arma :: uvec) - 我不知道向量的大小。我在Armadillo文档中找不到合适的函数,但是我还没有成功通过循环创建向量。我认为问题在于初始化矢量或跟踪其长度。

 arma::uvec foo(arma::vec x){
 arma::uvec vect;
 int nn=x.size();
 vect(0)=1;
 int ind=0;
 for (int i=0; i<nn; i++){
     if ((x(i)>0)){
        ind=ind+1;
        vect(ind)=i;
     }
 }
   return vect;
}

错误消息为:Error: Mat::operator(): index out of bounds.

我不想将1分配给向量的第一个元素,但如果需要可以使用它。

PS:我真的想知道如何通过追加获得未知长度的向量,这样即使在更一般的情况下我也可以使用它。

2 个答案:

答案 0 :(得分:6)

从性能的角度来看,向向量重复附加元素是非常糟糕的主意,因为它会导致重复的内存重新分配和复制。

有两种主要解决方案。

  1. 将向量的大小设置为操作的理论最大长度(在本例中为nn),然后使用循环设置向量中的某些值。到目前为止,您需要为向量中的set元素数保留一个单独的计数器。在循环之后,使用.head()函数获取向量的子向量。这里的优点是只有一个副本。

  2. 另一种解决方案是使用两个循环,以减少内存使用量。在第一个循环中计算出向量的最终长度。然后将矢量的大小设置为最终长度。在第二个循环中设置向量中的元素。显然使用两个循环的效率低于一个循环,但它可能仍然比附加循环快得多。

  3. 如果你仍然想成为一个懒惰的编码器并且无效地附加元素,请使用.insert_rows()函数。

    作为旁注,您的foo(arma::vec x)已经在不必要地复制输入向量。默认情况下,C ++中的参数按值传递,这基本上意味着C ++在运行函数之前会复制x。要避免这种不必要的副本,请将您的功能更改为foo(const arma::vec& x),这意味着将常量引用更改为x&在这里至关重要。

答案 1 :(得分:0)

除了mtall的回答,我同意, 对于不需要性能的情况,我使用了这个:

void uvec_push(arma::uvec & v, unsigned int value) {
    arma::uvec av(1);
    av.at(0) = value;
    v.insert_rows(v.n_rows, av.row(0));
}