C++ 如何逐个添加两个 STL 向量的元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3376124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add element by element of two STL vectors?
提问by Ivan
The question is quite dumb, but I need to do it in a very efficient way - it will be performed over an over again in my code. I have a function that returns a vector, and I have to add the returned values to another vector, element by element. Quite simple:
这个问题很愚蠢,但我需要以一种非常有效的方式来做——它将在我的代码中再次执行。我有一个返回向量的函数,我必须将返回的值逐个元素添加到另一个向量中。非常简单:
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
The mathematical operation that I'm trying to do is
我想做的数学运算是
u[i] = u[i] + v[i] for all i
u[i] = u[i] + v[i] 对于所有 i
What can be done?
可以做什么?
Thanks
谢谢
EDIT: added a simple initialization, as that is not the point. How should result be initialized?
编辑:添加了一个简单的初始化,因为这不是重点。结果应该如何初始化?
回答by Jon Reid
It sure looks like the problem is accessing values of result
that don't exist. tzaman shows how to initialize result to 10 elements, each with value 0.
看起来问题确实是访问result
不存在的值。tzaman 展示了如何将结果初始化为 10 个元素,每个元素的值为 0。
Now you need to call the transform
function (from <algorithm>), applying the plus
function object (from <functional>):
现在您需要调用transform
函数(来自 <algorithm>),应用plus
函数对象(来自 <functional>):
std::transform(result.begin(), result.end(), result_temp.begin(),
result.begin(), std::plus<double>());
This iterates over result
and result_temp
, applies plus
that adds doubles, and writes the sum back to result
.
这将迭代result
和result_temp
,应用plus
加倍,并将总和写回result
。
回答by James McNellis
If you are trying to append one vector
to another, you can use something like the following. These are from one of my utilities libraries--two operator+=
overloads for std::vector
: one appends a single element to the vector
, the other appends an entire vector
:
如果您尝试将一个附加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;
}
If you are trying to perform a summation (that is, create a new vector
containing the sums of the elements of two other vector
s), you can use something like the following:
如果您正在尝试执行求和(即创建一个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;
}
You could similarly implement an operator+=
overload.
您可以类似地实现operator+=
重载。
回答by gerardw
A concrete example of Jon Reid's answer:
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);
回答by tzaman
You need to initialize result
to all zeros first; just declaring the variable doesn't actually allocate any elements.
您需要先初始化result
为全零;只是声明变量实际上并没有分配任何元素。
Try this:
尝试这个:
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];
回答by Steve Jessop
If your code is segfaulting then that's a correctness issue, not an efficiency issue.
如果您的代码出现段错误,那么这是一个正确性问题,而不是效率问题。
To achieve "u[i] = u[i] + v[i] for all i", I would do basically what you did:
为了实现“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];
}
If you really care about performance of your program (that is, you've written a basic version and it's so slow that your program is failing some requirement, and you've proved that this is the code where much of the time is taken), then you could try:
如果你真的关心你的程序的性能(也就是说,你写了一个基本版本,它太慢以至于你的程序不能满足某些要求,并且你已经证明这是花费大部分时间的代码) ,那么你可以试试:
- switching on lots of optimization in your compiler (actually, I usually do this by default even when there isn't a performance problem),
- using iterators instead of indexes (rarely makes much difference, but it's easy enough to compare the two),
- unrolling the loop a bit (can make a worthwhile speed difference, but that's quite sensitive to the particular case, and it encourages coding errors).
- looking at platform-specific SIMD instructions rather than C++. Then use embedded assembler or compiler intrinsics for those instructions.
- 在编译器中开启大量优化(实际上,即使没有性能问题,我通常也会默认执行此操作),
- 使用迭代器而不是索引(很少有太大区别,但比较两者很容易),
- 稍微展开循环(可以产生有价值的速度差异,但这对特定情况非常敏感,并且会导致编码错误)。
- 查看特定于平台的 SIMD 指令而不是 C++。然后对这些指令使用嵌入式汇编器或编译器内在函数。
Nevertheless, you have no business worrying about performance before your code is correct ;-). "Make it work, make it right, make it fast" is a reasonable motto, although often you don't need to go as far as step 3.
尽管如此,在您的代码正确之前,您不必担心性能;-)。“让它工作,让它正确,让它快速”是一个合理的座右铭,尽管通常你不需要走到第 3 步。
std::valarray
actually has exactly the operator+=
you want. Before you replace all your vectors with valarrays, be aware that doesn't necessarily mean it's any "more efficient" than a simple loop - I don't know how seriously implementers take valarray
. You can always look at the source in your implementation. I also don't know why the multiple-data arithmetic functionality of valarray
wasn't defined as part of vector
, but there's usually a reason.
std::valarray
其实有operator+=
你想要的。在用 valarrays 替换所有向量之前,请注意这并不一定意味着它比简单循环“更有效” - 我不知道实现者有多认真valarray
。您始终可以查看实现中的源代码。我也不知道为什么 的多数据算术功能valarray
没有定义为 的一部分vector
,但通常是有原因的。
回答by Jonathan M Davis
The code seems fine, but my first inclination would be to alter whatever code is filling the vector with values to add to the values in the first vector to take in a reference to the first vector and add directly to it rather than creating a new vector that gets returned. That's just inefficient.
代码看起来不错,但我的第一个倾向是改变任何用值填充向量的代码,以添加到第一个向量中的值,以获取对第一个向量的引用并直接添加到它,而不是创建一个新向量那得到回报。那只是低效的。
If you can't alter the function in that way, perhaps you can alter it so that it takes a reference to a vector which it clears and then inserts the values into so that you aren't copying vectors around. That can get to be expensive if you're doing it much.
如果你不能以这种方式改变函数,也许你可以改变它,以便它引用一个向量,它清除然后插入值,这样你就不会复制向量。如果你做得太多,那可能会变得很昂贵。
Another nitpick if you're trying to get this as fast as possible, you should use pre-increment with iterators rather than post-increment. The temporary that post-increment creates can't be optimized away when dealing with overloaded operators rather than built-in types. So, you keep creating and destroying a temporary every iteration of your loop. EDIT:As was pointed out in the comments, you're using indices here rather than iterators (I obviously wasn't paying enough attention), so this bit of advice doesn't really apply here. However, in cases where you areusing iterators, it's still valid.
另一个吹毛求疵,如果你想尽快得到它,你应该使用带迭代器的预增量而不是后增量。在处理重载运算符而不是内置类型时,无法优化后增量创建的临时性。因此,您在循环的每次迭代中不断创建和销毁临时文件。 编辑:正如评论中所指出的,您在这里使用索引而不是迭代器(我显然没有给予足够的关注),所以这条建议在这里并不真正适用。然而,在你的情况下被使用迭代器,它仍然是有效的。
Other than that, if you're trying to add all of the elements of two vectors togther, what you have is probably about as efficient a solution as you're going to get. There are better ways if what you're concerned about is inserting the elements of one vector into another, but if you're just adding their values together, what you have looks good. I would expect that using any STL algorithms would be at best just as fast and likely slower due to extra function calls, but you'd probably have to profile it to be sure.
除此之外,如果您尝试将两个向量的所有元素加在一起,那么您所拥有的解决方案可能与您将获得的解决方案一样有效。如果您关心的是将一个向量的元素插入另一个向量,则有更好的方法,但如果您只是将它们的值加在一起,那么您所拥有的看起来不错。由于额外的函数调用,我希望使用任何 STL 算法充其量也一样快,但可能会更慢,但您可能必须对其进行分析才能确定。