如何逐个元素添加两个STL向量?

时间:2010-07-30 23:45:43

标签: c++ stl vector

这个问题非常愚蠢,但我需要以非常有效的方式完成 - 它将在我的代码中重复执行。我有一个返回向量的函数,我必须逐个元素地将返回的值添加到另一个向量。很简单:

vector<double> result;
vector<double> result_temp
for(int i=0; i< 10; i++) result_temp.push_back(i);

result += result_temp //I would like to do something like that.
for(int i =0; i< result_temp.size();i++)result[i] += result_temp[i]; //this give me segfault

我正在尝试的数学运算是

u [i] = u [i] + v [i] for all i

可以做些什么?

由于

编辑:添加了一个简单的初始化,因为这不是重点。如何初始化结果?

7 个答案:

答案 0 :(得分:31)

如果您尝试将一个vector附加到另一个operator+=,则可以使用以下内容。这些是来自我的一个实用程序库 - std::vector的两个vector重载:一个将一个元素追加到vector,另一个追加整个template <typename T> std::vector<T>& operator+=(std::vector<T>& a, const std::vector<T>& b) { a.insert(a.end(), b.begin(), b.end()); return a; } template <typename T> std::vector<T>& operator+=(std::vector<T>& aVector, const T& aObject) { aVector.push_back(aObject); return aVector; }

vector

如果您尝试执行求和(即创建包含两个其他vector s的元素总和的新#include <algorithm> #include <functional> template <typename T> std::vector<T> operator+(const std::vector<T>& a, const std::vector<T>& b) { assert(a.size() == b.size()); std::vector<T> result; result.reserve(a.size()); std::transform(a.begin(), a.end(), b.begin(), std::back_inserter(result), std::plus<T>()); return result; } ),您可以使用以下内容:

operator+=

您可以类似地实施{{1}}重载。

答案 1 :(得分:31)

看起来问题似乎是访问不存在的result值。 tzaman展示了如何将结果初始化为10个元素,每个元素的值为0。

现在您需要调用transform函数(来自&lt; algorithm&gt;),应用plus函数对象(来自&lt; functional&gt;):

std::transform(result.begin(), result.end(), result_temp.begin(),
               result.begin(), std::plus<double>());

这会迭代resultresult_temp,应用plus添加双倍,并将总和写回result

答案 2 :(得分:8)

Jon Reid回答的一个具体例子:

std::array<double,3> a = {1, 2, 3};
std::array<double,3> b = {4, 5, 6};
std::transform(a.begin( ), a.end( ), b.begin( ), a.begin( ),std::plus<double>( ));
ASSERT_TRUE(a[0] == 5);
ASSERT_TRUE(a[1] == 7);
ASSERT_TRUE(a[2] == 9);

答案 3 :(得分:1)

您需要先将result初始化为全零;只是声明变量实际上并没有分配任何元素。

试试这个:

vector<double> result(10); // default-initialize to 10 elements
vector<double> result_temp;
for(int i=0; i< 10; i++) 
    result_temp.push_back(i);

for(int i =0; i< result_temp.size();i++)
    result[i] += result_temp[i];

答案 4 :(得分:1)

如果您的代码是segfaulting,那么这是一个正确性问题,而不是效率问题。

要实现“u [i] = u [i] + v [i] for all i”,我基本上会做你所做的:

assert(u.size() == v.size()); // will fail with your initialization code, since
                              // your "result" has size 0, not size 10.
                              // perhaps do u.resize(v.size());
for (size_t i = 0; i < u.size(); ++i) {
    u[i] += v[i];
}

如果你真的关心你的程序的性能(也就是说,你已经编写了一个基本版本而且它的速度很慢,以至于你的程序失败了一些要求,并且你已经证明这是大多数时间的代码(),然后你可以尝试:

  • 在编译器中开启大量优化(实际上,即使没有性能问题,我通常会默认执行此操作),
  • 使用迭代器而不是索引(很少有差别,但很容易比较两者),
  • 稍微展开循环(可以产生有价值的速度差异,但这对特定情况非常敏感,并且它会鼓励编码错误)。
  • 查看特定于平台的SIMD指令而不是C ++。然后使用嵌入式汇编程序或编译器内在函数来执行这些指令。

然而,在代码正确之前,你没有业务担心性能;-)。 “让它发挥作用,做到正确,加快速度”是一个合理的座右铭,尽管通常你不需要走到第3步。

std::valarray实际上完全符合您想要的operator+=。在用valarrays替换所有向量之前,请注意,这并不一定意味着它比简单的循环更“有效” - 我不知道实现者如何认真对待valarray。您始终可以查看实施中的源代码。我也不知道为什么valarray的多数据算术功能没有被定义为vector的一部分,但通常有一个原因。

答案 5 :(得分:0)

我和@James McNellis在一起 - 只要resultresult_temp的长度相同,此代码就是正确的。

另外 - 为什么你声明result,但是使用变量result_v - 代码是如何实际编写的?如果是这样,那就是一个问题

答案 6 :(得分:0)

代码看起来很好,但我的第一个倾向是改变填充向量的任何代码,使用值添加到第一个向量中的值以引入第一个向量并直接添加到它而不是创建一个返回的新向量。那效率很低。

如果你不能以这种方式改变函数,也许你可以改变它,以便它引用一个它清除的向量,然后插入值,这样你就不会复制向量。如果你做得太多,这可能会变得昂贵。

如果你想尽快得到这个,你应该使用迭代器的预增量而不是后增量。在处理重载运算符而不是内置类型时,无法优化后增量创建的临时值。因此,您不断创建和销毁循环的每次迭代。 编辑:正如评论中指出的那样,你在这里使用索引而不是迭代器(我显然没有给予足够的重视),所以这里的建议并不适用。但是,如果 使用迭代器,它仍然有效。

除此之外,如果你试图将两个向量的所有元素添加到其他内容中,那么你所拥有的内容可能就像你将获得的解决方案一样高效。如果您关注的是将一个向量的元素插入到另一个向量中,那么有更好的方法,但如果您只是将它们的值一起添加,那么您所拥有的内容看起来很好。我希望使用任何STL算法最多只是因为额外的函数调用而速度很快而且可能更慢,但你可能不得不对它进行分析以确定。