首页  >  文章  >  后端开发  >  为什么 `push_back` 会在向量中触发多个复制构造函数调用?

为什么 `push_back` 会在向量中触发多个复制构造函数调用?

Barbara Streisand
Barbara Streisand原创
2024-11-01 07:17:02533浏览

Why Does `push_back` Trigger Multiple Copy Constructor Calls in a Vector?

向量 Push_back 和多次复制构造函数调用的奥秘

使用向量时,人们可能期望 Push_back 操作只需要少量复制构造函数调用。但是,某些情况可能会出现意外行为,例如多次调用。

考虑以下代码片段:

<code class="cpp">class Myint {
    int my_int;
public:
    Myint() : my_int(0) { /* ... */ }
    Myint(const Myint& x) : my_int(x.my_int) { /* ... */ }
};

int main() {
    vector<Myint> myints;
    Myint x;

    myints.push_back(x); // Call 1
    x.set(1);
    myints.push_back(x); // Call 2
}</code>

直观上,我们预计有两个复制构造函数调用:一个用于第一个 push_back第二个是另一个。然而,输出却讲述了一个不同的故事:

Call 1 (default constructor)
Call 2 (copy constructor: my_int = 0)
Call 3 (copy constructor: my_int = 0)
Call 4 (copy constructor: my_int = 1)

为什么需要额外的调用?

内部向量动力学

在内部,向量通常会分配一定量的内存贮存。当分配的空间耗尽时,向量必须重新分配更多内存。此重新分配会触发将现有元素复制到新内存中。

在给定的代码中,第二个push_back需要重新分配。尽管 Myint 的构造函数仅被调用两次,但复制构造函数却被使用了 3 次。这是因为复制构造函数用于将第一个元素移动到新分配的内存中,并使用其原始值 (my_int = 0) 进行初始化,然后再次调用复制构造函数来创建第二个元素,并使用更新后的值进行初始化 ( my_int = 1).

优化性能

为了减少这些不必要的副本,建议:

  • 预留内存:通过增加向量的初始容量,您可以防止重新分配并最大限度地减少复制操作。
  • 使用 Emplace_back:此方法允许您直接就地构造元素,避免复制或移动。

在这种情况下,使用保留来预分配内存可以有效地将复制构造函数调用减少到两次。此外,emplace_back(0) 将完全消除复制,从而实现最佳性能。

以上是为什么 `push_back` 会在向量中触发多个复制构造函数调用?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn