不能将迭代器分配给二进制函数中的常量输入向量

时间:2012-04-24 16:58:44

标签: c++ vector binary-operators

我正在尝试编写一个二进制函数,它接受两个向量(长度相同)并按值添加它们。由于某种原因,以下代码不起作用:

struct Plusval : binary_function <std::vector<int>,std::vector<int>,std::vector<int> > 
{
  std::vector<int> operator() (const std::vector<int>& x, const std::vector<int>& y) const
{
    std::vector<int> ret(x);
    std::vector<int>::iterator itx,ity;
    ity=y.begin();
    for (itx=ret.begin();itx<ret.end();++itx)
    {
        ret[*itx]+=y[*ity];
        ++ity;
    }
    return ret;
  }
};

我收到错误,我不能做ity = y.begin() 但是,以下代码可以正常工作

struct Plusval : binary_function <std::vector<int>,std::vector<int>,std::vector<int> > 
{
  std::vector<int> operator() (const std::vector<int>& x, const std::vector<int>& y) const
{
    std::vector<int> ret(x);
    std::vector<int> yloc(y);
    std::vector<int>::iterator itx,ity;
    ity=yloc.begin();
    for (itx=ret.begin();itx<ret.end();++itx)
    {
        ret[*itx]+=yloc[*ity];
        ++ity;
    }
    return ret;
  }
};

显然,第二个版本需要更长的时间(因为它必须复制一个额外的向量)。是因为输入是一个常量向量吗?如果是,是否有任何理由需要?请注意,我打算使用此函数作为boost :: mpi中allreduce()函数的输入,如果这有任何区别

4 个答案:

答案 0 :(得分:4)

您将ity定义为vector::iterator yconst并返回const_iterator

更重要的是:不要使用binary_function。适配器已被弃用。

此外,您的功能不能满足您的需求。 * itx返回存储在itx指向的位置的值,您可以使用它来索引您打算返回vector

我会用二进制transform来写这个。

std::vector<int> res;
std::transform(begin(x), end(x), begin(y), 
               std::back_inserter(res), std::plus<int>());

答案 1 :(得分:1)

错误是您不能将非const迭代器与const容器一起使用,因为这会破坏const正确性。你应该在第二个参数上使用std::vector<int>::const_iterator

除此之外,第一个块中的实现不会按照您的声明执行。您正在迭代容器并使用存储的值索引到容器中并在那里进行更新。如果你真的想要从两个容器中添加值,那么它比这简单得多:

struct PlusVal
{
   std::vector<int> operator()( std::vector<int> lhs, std::vector<int> const& rhs )
   {
      assert( lhs.size() == rhs.size() );
      for (std::vector<int>::size_type i = 0; i < lhs.size; ++i )
         lhs[i] += rhs[i];
      return lhs;
   }
};

如果你想用迭代器做到这一点,它同样很简单:

struct PlusVal
{
   std::vector<int> operator()( std::vector<int> lhs, std::vector<int> const& rhs )
   {
      assert( lhs.size() == rhs.size() );
      std::vector<int>::iterator it = lhs.begin(), end = lhs.end();
      std::vector<int>::const_iterator rit = rhs.begin();
      while ( it != end )
         *it++ += *rit++;
      return lhs;
   }
};

答案 2 :(得分:0)

您正在寻找std::vector::const_iterator类型

std::vector<int> operator() (const std::vector<int>& x, const std::vector<int>& y)
{
  std::vector<int> result;

  // Not strictly necessary, but helps with performance a bit
  result.reserve(std::min(x.length(), y.length());

  for (std::vector<int>::const_iterator x_it = x.begin(),
                                      y_it = y.begin();
      x_it != x.end() && y_it != y.end();
      ++x_it, ++y_it)
  {
   result.push_back(*x_it + *y_it);
  }

  return result;
}

答案 3 :(得分:0)

看起来你已经得到了一两个合理的答案;我只想指出一个替代方案。虽然我在提及它时犹豫不决,std::valarray非常适合我,但我无法抗拒:

std::valarray<int> x;
std::valarray<int> y;

// code to populate x and y elided

x += y;

有几个月(左右),我发现valarray会变得如此简单,我发现真的很遗憾它已经丢失并被遗忘(然后我会想到像slice,{{1}这样的事情。 },gsliceslice_array等,并希望我根本没有想到它。