如何通过两个STL向量的元素添加元素?

问题描述:

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

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]对于所有i

可以做些什么?

感谢

编辑:添加了一个简单的初始化,因为这是不是问题的关键。应该如何初始化结果?

+5

你能发布一些编译代码? “这给了我一个段错误”在没有看到这些向量是如何初始化的情况下并不是特别有用。最可能的问题是其中一个向量比另一个长。在没有看到所有代码的情况下很难确定代码是错误的:-) – 2010-07-30 23:48:10

+0

http://www.boost.org/doc/libs/1_43_0/libs/numeric/ublas/doc/operations_overview.htm – Anycorn 2010-07-30 23:57:41

如果您试图将一个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 S中的元素之和新vector),你可以使用类似以下内容:

#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+=超载。

+0

谢谢,但我并没有试图将值附加到向量的末尾,我试图将矢量元素的现有值与另一个向量的值相加。矢量的大小始终是固定的。 – Ivan 2010-07-30 23:59:16

+2

@Ivan:看到编辑;直到我看到你的评论回复格雷格的回答时,我并不完全确定你在找什么。 – 2010-07-31 00:00:11

+2

@詹姆斯忽略我的原始评论 - 现在你已经看中和相关的代码:) – 2010-07-31 00:00:42

我与@詹姆斯麦克奈利斯 - 这段代码似乎是正确的,只要resultresult_temp是相同的长度。

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

您需要首先将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]; 

的代码看起来不错,但我的第一个倾向是改变任何代码填充向量与值添加到值在第一载体采取的参考第一个矢量并直接添加到它而不是创建一个返回的新矢量。这只是低效率。

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

如果您试图尽可能快地获得此代码,那么您应该使用迭代器的预增量而不是后增量。在处理重载操作符而不是内置类型时,后增量创建的临时操作无法优化。所以,你一直在创建和销毁循环的每一次迭代。编辑:正如在评论中指出的那样,你在这里使用索引而不是迭代器(我显然没有给予足够的关注),所以这个建议在这里并不适用。但是,在使用迭代器的的情况下,它仍然有效。除此之外,如果您试图将两个向量的所有元素都添加到其中,那么您拥有的解决方案可能与您将要获得的解决方案一样高效。如果你关心的是将一个向量的元素插入另一个向量,有更好的方法,但是如果你只是将它们的值加在一起,你看起来不错。我期望使用任何STL算法最多只会因为额外的函数调用而快速且可能较慢,但您可能必须对其进行配置才能确定。

+1

“你应该使用迭代器而不是后增量进行预增量”。没错,但他没有使用迭代器,他使用了整数索引。很难做出前和后增量之间的表现案例;-) – 2010-07-31 00:30:10

+0

啊,很好的捕获。我没有给予足够的关注。我很少使用索引而不是迭代器,并且我对后增加的直觉反应非常消极。除非需要后期增量,否则我总是坚信使用前增量。这样,您永远不必担心临时性是否会被优化。然而,在这种情况下,编译器应该没有问题优化它,后增量和预增量一样有效。 – 2010-07-31 01:07:11

+0

是的,即使除了可能出现的性能问题,我还是喜欢预先增量,但是由于有争议的原因,我认为它更清晰可读。 “Increment i”拼写为“++ i”。很少有人同意。 – 2010-07-31 02:23:34

它肯定看起来像问题是存取result不存在的值。 tzaman说明了如何初始化结果到10个元素,每个具有0值

现在需要调用transform函数(从<算法>),应用plus功能对象(从<官能>):

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

此操作重复执行resultresult_temp,应用plus,该值增加了两倍,并将总和写回result

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

为了实现 “U [i] = U [I] + V [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的一部分,但通常有一个原因。

+0

就像座右铭。 – Vincent 2014-08-19 12:56:05

乔恩·里德的回答的一个具体的例子:

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);