8

是否有任何有效且惯用的方法来执行以下操作?

std::vector<int> a = { 1, 2, 3, 4 };
std::vector<int> b = { 5, 6, 7, 8 };

for (std::size_t i = 0 ; i < a.size() ; ++i)
{
    a[i] += b[i];
}

我试图避免使用括号/索引表示法,并且只使用迭代器,以便操作可以与任何具有前向迭代器的容器一起使用。我想到了以下解决方案:

std::vector<int> a = { 1, 2, 3, 4 };
std::vector<int> b = { 5, 6, 7, 8 };

std::transform(a.begin(), a.end(),
               b.begin(),
               a.begin(),
               std::plus<int>());

但是,有冗余,a.begin()我只能使用+而不是+=. 标准库中是否有一些算法可以让我在没有任何冗余的情况下使用迭代器,或者我必须手动编写完整的循环?

4

6 回答 6

9

也许是为了成为惯用语,但从未完全做到:

std::valarray<int> a = { 1, 2, 3, 4 };
std::valarray<int> b = { 5, 6, 7, 8 };

现在你可以做到这些

std::valarray<int> c = a + b; //apply '+' element-wise; store result in c

a += b;  //apply '+=' element-wise 

有关更多详细信息,请参阅std::valarray 的文档。

于 2013-09-17T19:00:03.747 回答
4

冗余有什么问题a.begin()

如果您对此不满意,请发明自己的算法:transform_inplace

template <class InputIterator, class OutputIterator, class BinaryOperator>
OutputIterator transform_inplace (InputIterator first,
                                  InputIterator last,
                                  OutputIterator result,
                                  BinaryOperator op)
{
  while (first != last) {
    *result = op(*result, *first);
    ++result; 
    ++first;
  }
  return result;
}
于 2013-09-17T18:51:46.903 回答
4

如果您不止一次使用它,并且您对标准库精神下的简单界面感兴趣,您可以为特定用例创建一个简单的模板类(我将其称为“范围增量”),并写下类似的东西:

#include<vector>
#include<algorithm>
#include<iostream>

template<typename InputIt>
InputIt range_increment(InputIt dbeg, InputIt dend, InputIt sbeg) {
  while(dbeg!=dend) {
    *(dbeg++) += (*sbeg++);
  }
  return dbeg;
}

int main() {
  std::vector<int> a = { 1, 2, 3, 4 };
  std::vector<int> b = { 5, 6, 7, 8 };

  range_increment(a.begin(), a.end(), b.begin());

  for(auto x:a) {
    std::cout<<x<<std::endl;
  }
}

产生:

6
8
10
12
于 2013-09-17T19:37:01.750 回答
2

不确定我是否称其为“惯用语”,但是:

assert(a.size()==b.size());
auto bi = b.begin();
for (auto& i : a) {
  i += *(bi++);
}

很简洁。

于 2013-09-17T18:52:52.570 回答
1

我找不到我正在寻找的那种通用函数,最后使用了我命名的以下函数range_map(“用两个给定的范围映射给定的函数元素”)。正如评论所指出的,它实际上只不过是一个二进制文件std::for_each

template<class InputIt1, class InputIt2, class BinaryOperation>
void range_map(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, BinaryOperation binary_op)
{
    while (first1 != last1) {
        binary_op(*first1++, *first2++);
    }
}

plus_assign通过以下方式创建了这个类:

template<typename T>
struct plus_assign
{
    void operator()(T &lhs, const T &rhs) const 
    {
        lhs += rhs;
    }
};

然后我的代码变成:

std::vector<int> a = { 1, 2, 3, 4 };
std::vector<int> b = { 5, 6, 7, 8 };

range_map(a.begin(), a.end(),
          b.begin(),
          plus_assign<int>());

function 也有对应的一元对应物range_map,用于将给定的仿函数映射到一个范围:

template<class InputIt, class BinaryOperation>
void range_map(InputIt first, InputIt last,
               UnaryOperation unary_op)
{
    while (first != last) {
        unary_op(*first1++);
    }
}
于 2013-09-17T20:50:33.537 回答
0

使用运算符重载

#include <vector>

std::vector<int>& operator += (std::vector<int>& a, std::vector<int> const& b)
{
    for(size_t i = 0; i != a.size(); ++i)
        a[i] += b[i];

    return a;
}

int main(int argc, char * argv[])
{
   std::vector<int> a { 1, 3, 5, 7, 9};
   std::vector<int> b { 2, 4, 6, 8, 10};

   a += b;

   return 0;
}
于 2013-09-18T05:41:10.073 回答