使用 push_back(x) 还是使用索引(capacity)更快?

huangapple go评论60阅读模式
英文:

Is it faster to use push_back(x) or using an index (capacity)?

问题

Method 1:

我学到了向 `vector` 中插入元素的两种方法。

我一直在思考哪种方法更快,因为我在处理时间限制。

方法1
```cpp
int n;
cin >> n;
vector<int> v(n);
for(int i = 0; i < n; i++){
  cin >> v[i];
}

方法2:

int n;
cin >> n;
vector<int> v;
for(int i = 0; i < n; i++){
  int x;
  cin >> x;
  v.push_back(x);
}

如果您有更好的方法建议,将不胜感激!


[1]: https://i.stack.imgur.com/M2AcZ.png
英文:

I learned 2 ways of inserting elements into a vector.

And I've been wondering which way is faster since I'm working with time limits.

Method 1:

int n;
cin&gt;&gt;n;
vector&lt;int&gt; v(n);
for(int i = 0;i&lt;n;i++){
  cin&gt;&gt;v[i];
}

Method 2:

int n;
cin&gt;&gt;n;
vector&lt;int&gt; v;
for(int i = 0;i&lt;n;i++){
  int x;
  cin&gt;&gt;x;
  v.push_back(x);
}

If you have a better method to suggest, it'd be appreciated!

答案1

得分: 7

两者都有问题:
应该使用 reserve(n)

int n;
cin >> n;
vector<int> v;
v.reserve(n);
for(int i = 0; i < n; ++i){
    int x;
    cin >> x;
    v.emplace_back(x);
}

在第一个版本中:设置大小。

在这里,你面临的问题是你正在构造数组中的所有元素。对于整数来说,这可能微不足道。但如果我们将其扩展到具有需要为每个元素调用构造函数的非整数类型,然后你使用赋值运算符复制它们,那就会成为一个问题。

第二个选择:push_back

在这里,你面临底层存储可能被重新分配的风险(可能多次)。每次重新分配都需要将数据从旧存储复制到新存储。

对于整数来说,这仍然不算问题,但对于具有构造函数和析构函数的类型来说,这将会很痛苦。

推荐使用:emplace_back()

与需要完全构造对象的推送不同,你可以使用 emplace_back 并传入用于构造对象的对象。这允许向量原地构造对象。如果你有简单的整数或具有高效移动语义的类,那么这不是问题,但作为一种一般习惯是值得的。

英文:

Both have issues:
You should be using reserve(n)

int n;
cin &gt;&gt;  n;
vector&lt;int&gt; v;
v.reserve(n);
for(int i = 0; i &lt; n; ++i){
    int x;
    cin &gt;&gt; x;
    v.emplace_back(x);
}

In the first version: Setting size.

Here you have the issue that you are constructing all the elements in the array. Now for integers this may be insignificant. But if we extend this to non integer types that have a constructor that needs to be called for each element and then you are using the assignment operator to copy over them.

The second option: push_back

Here you run into the risk of the underlying storage being reallocated (potentially multiple times). Each time you re-allocate you need to copy the data from the old storage to the new storage.

Again this hurts for integers but really hurts for types with constructors and destructors.

Prefer: emplace_back()

Rather than pushing where you need a fully constructed object. You can use emplace_back and pass in the objects used to construct the object. This allows the vector to construct the object in place. If you have simple integers or classes with effecient move semantics then not an issue but worth it as a general habit.

答案2

得分: 1

方法1更快,因为它避免了对向量的基础数组进行重新分配的需要。

英文:

Method 1 is faster because it avoids the need for reallocation of the underlying array of the vector.

答案3

得分: 1

在你提到的两种方法中,方法1通常比方法2更快,因为它避免了在推入新元素时调整向量大小和移动元素的开销。在方法1中,向量在开始时被初始化为所需的大小,因此不需要重新分配或移动元素。

对于小型或中等大小的向量,性能差异可能不足以引起关注(当你处理更大规模的数据时,性能差异才会明显)。

如果你有时间限制并且需要进一步优化性能,你可以尝试一种混合方法,结合了这两种方法的优点。以下是一个示例:

int n;
cin >> n;
vector<int> v;
v.reserve(n); // 为n个元素预分配内存
for (int i = 0; i < n; i++) {
  int x;
  cin >> x;
  v.push_back(x);
}

在这种方法中,你使用v.reserve(n)来为向量预先分配内存,以容纳n个元素,这可以帮助避免在push_back操作期间频繁重新分配内存。对于较大的向量,这可以提供一些性能改进!

英文:

Between the two methods you mentioned, Method 1 is generally faster than Method 2 because it avoids the overhead of resizing the vector and moving elements when pushing back new elements. In Method 1, the vector is initialized with the required size upfront, so there is no need for reallocation or element shifting.

For small or moderate-sized vectors, the performance difference may not be significant enough to be a concern (When you deal with a greater scale, than you'll actually observe a difference in performance).

If you're working with a time limit and need to optimize the performance further, you can try a hybrid approach that combines the advantages of both methods. Here's an example:

    int n;
    cin &gt;&gt; n;
    vector&lt;int&gt; v;
    v.reserve(n); // Reserve memory for n elements
    for (int i = 0; i &lt; n; i++) {
      int x;
      cin &gt;&gt; x;
      v.push_back(x);

}

In this approach, you use v.reserve(n) to preallocate memory for n elements in the vector, which can help avoid frequent reallocations during the push_back operations. This can provide some performance improvement over Method 2, especially for larger vectors!

huangapple
  • 本文由 发表于 2023年6月2日 02:04:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384567.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定