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

C++ 理解将对象插入向量时的构造、复制和销毁,c++,vector,constructor,stl,copy-constructor,C++,Vector,Constructor,Stl,Copy Constructor,我试图理解STL如何处理对象的插入。 我知道STL调用构造函数或从临时 这是我试图理解的代码: #include <iostream> #include <string> #include <vector> using namespace std; class A { public: int ObjId;; A(int id) : ObjId(id) { cout << "C

我试图理解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不同。为什么要复制构造两个对象,并且两个对象的ID都为0,而不是2

有人能帮我理解这种行为吗


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

复制构造函数使ObjId保持未初始化状态,因此当访问该值时,程序的行为是未定义的

至于第二部分,我不知道发生了什么,也不知道为什么它与第一次插入不同,唯一的例外是ID不同。为什么要构造两个对象

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

这意味着向量通常初始化为1的容量


一个实验并不能说明向量通常做什么。似乎在第一次推送之后,您的系统上的容量实际上是一个容量。无法保证它在其他情况下(如std::vector的其他实现)会是一个。在第一种情况下,您将ObjId保持为未初始化状态,这意味着您很幸运插入了0,但基本上也可以看到任何值

通过键入Aconst A&other{…},您可以定义自己的复制构造函数,这意味着您可以显示每个字段是如何复制的,因此在构造函数中缺少ObjId=other.ObjId语句


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

我不理解为什么复制的对象ID为0,而不是1。您的复制构造函数不复制任何内容…我更喜欢使用复制构造函数成员初始化。所以一个标准A&objToCpy:ObjidobjToCpy.Objid{谢谢。我错了。我更改了复制构造函数编辑了问题,但第二次插入时仍然看到多个对象。谢谢。你是对的。当我保留时,它工作了。你是对的!当我保留10时,得到了我预期的行为。谢谢。这意味着向量通常初始化为1的容量?是的,就是我向量的这个特定实现的初始值。但是,我不确定初始值是否为0,并且无论何时添加元素,它都会分配任何额外的内存。但这里不是关键值。保持ObjId未初始化会导致未定义的行为,实际上,未定义的行为不会给您带来预期的结果是最糟糕的,因为你不会发现它,直到为时已晚