【问题标题】:Details of C++ Vector push_back()C++ 向量 push_back() 的详细信息
【发布时间】:2012-07-17 23:24:25
【问题描述】:

我正在尝试调试一个程序,这样做与我对 C++ 向量 push_back() 函数的理解产生了冲突。

为了说明我的观点,我编写了以下短程序:

#include <iostream>
#include <vector>
#include <cstdlib>

using std::cout;
using std::endl;
using std::vector;

class Test {
private:
  int mTestMember;
public:
  Test(int val);
  Test(const Test&);

  int GetValue() const;
};

Test::Test(int val)
{
  cout << "Constructor\n";
  mTestMember = val;
}

Test::Test(const Test& test)
{
  cout << "Copy Constructor\n";
  mTestMember = test.mTestMember;
  cout << "mTestMember: " << mTestMember << endl;
}

int main(){

  vector<Test> tests;
  tests.push_back(Test(int(5)));
  cout<< endl;
  tests.push_back(Test(int(6)));
  cout << endl;
  tests.push_back(Test(int(7)));

  return(0);
}

如果我编译并运行,我会得到以下输出:

Constructor
Copy Constructor
mTestMember: 5

Constructor
Copy Constructor
mTestMember: 6
Copy Constructor
mTestMember: 5

Constructor
Copy Constructor
mTestMember: 7
Copy Constructor
mTestMember: 5
Copy Constructor
mTestMember: 6

看起来,在 push_back() 函数的过程中,执行了作为参数传递给 push_back() 函数(我已经知道)的对象的副本,然后是其余的先前存在的元素也会从前面开始复制到新向量中。

我对流程的理解是否正确?

【问题讨论】:

    标签: c++ vector


    【解决方案1】:

    std::vector 将其元素存储在一个数组中。数组总是有固定的大小,所以如果你不断向std::vector 添加元素,它的底层数组最终会被填满。当数组已满并且您添加另一个元素(通过push_back 或另一个添加新元素的成员函数)时,它必须:

    1. 创建一个新的更大的数组,
    2. 将旧数组中的元素复制或移动(*)到新数组中,
    3. 将新元素插入到新数组中,然后
    4. 销毁旧数组

    这个过程称为重新分配std::vector 的正确实现应该以指数方式调整数组的大小。 Visual C++ std::vector 实现使用 1.5 倍的增长因子;其他实现可能使用不同的增长因子。


    (*) C++11 增加了对移动对象的支持。

    【讨论】:

    • @SethCarnegie:不允许(尽管对于小数组,它可能看起来那样)。它必须按一个因子调整大小,而不是简单地添加一个恒定数量的更多大小。否则将无法满足amortized constant 的要求。
    • 但是如果你只有几件物品并且系数相对较低,那么前几个 push_backs 可能会 +1。
    • @Wheels2050:我认为步骤 (2) 和 (3) 的顺序是实现定义的。不过,我手边没有规范。 (但是,我会在任何一种都可能首先发生的假设下进行操作:这与您的代码无关。)
    • MSVC 增长因子实际上是 1.5 倍。埋在实现中你可以看到它确实capacity() + capacity()/2
    • @JerryCoffin:是的,当然。添加。 [旁白:C++ 对象模型已经相当复杂;添加移动语义使它变得更加如此。移动语义使回答这样的问题变得更加困难:一方面,一方面想要提供一个简单的答案来描述观察到的行为。另一方面,希望提供一个完整、完全正确的答案,以免无意中误导。我不知道这里的其他人,但我确定我还没有弄清楚正确的平衡点在哪里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2018-06-27
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多