理解向向量中插入对象时的构造、复制和销毁

Understanding the construction, copy and destruction when inserting objects to a vector

我想了解 STL 如何处理对象的插入。 我知道 STL 从临时调用构造函数或复制构造。

这是我试图理解的代码:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class A
{
      public:
      int ObjId;;
      A(int id) : ObjId(id)
      {
            cout << "Constructing object with id: " << ObjId << endl;
      }

      A(const A& objToCpy)
      {
            ObjId = objToCpy.ObjId;
            cout << "Copying object with id: " << ObjId << endl;
       }

      ~A()
      {
            cout << "Destructing object with id: " << ObjId << endl;
      }
};


int main()
{
      std::vector<A> vecOfA;

      vecOfA.push_back(A(1));

      cout << "....................." << endl << endl;

      vecOfA.push_back(A(2));

      return 0;
}

这给出了以下输出:

正在构造 ID 为 1 的对象

正在复制 ID 为 1 的对象

正在销毁 id 为 1 的对象

................

正在构造 ID 为 2 的对象

正在复制 ID 为 2 的对象

正在复制 ID 为 1 的对象

正在销毁 id 为 1 的对象

正在销毁 id 为 2 的对象

................

正在销毁 id 为 1 的对象

正在销毁 id 为 2 的对象

第一次插入我能看懂。创建一个 ID=1 的临时对象,然后将其复制构造并插入到向量中。这个临时的然后被破坏了。

但是,我不明白为什么复制的对象ID=0,而不是1。

至于第二部分,我不知道这是怎么回事,为什么它与第一个插入部分不一样,唯一的例外是ID不同。为什么复制构造了2个对象,而且都是ID=0,而不是2.

谁能帮我理解这种行为?

However, I do not understand why the copied object has ID=0, and not 1.

您的复制构造函数使 ObjId 未初始化,因此在访问该值时程序的行为未定义。


As for the second part, I have no idea what is going on and why it is not identical to the first insertion, with the only exception of the ID being different. Why are 2 objects copy constructed

这是因为 std::vector 的动态数组数据结构的工作原理。数组不能调整大小。一旦vector的内部数组太小,就会创建一个更大的数组,将旧的元素复制(或移动)到新的数组中,并销毁旧的数组。


That means vector usually initialize to a capacity of 1?

一个实验并不能说明向量 通常 的作用。看起来在第一次推送之后,在这种情况下您的系统上的容量确实是一个。不能保证在其他情况下它会是一个(例如 std::vector 的其他实现)。

在第一种情况下,您保留 ObjId 未初始化,这意味着您很幸运插入了 0,但基本上也可以是任何可见的值。

通过键入 A(const A& other) {...},您定义了自己的复制构造函数,这意味着您显示了每个字段的复制方式,因此您错过了构造函数中的 ObjId = other.ObjId 语句。

第二种情况发生是因为您的矢量正在调整大小,因此它必须将所有元素从旧存储复制到新的、更大的、也适合新元素的存储。