【问题标题】:Understanding the construction, copy and destruction when inserting objects to a vector了解将对象插入向量时的构造、复制和销毁
【发布时间】:2018-09-11 09:59:50
【问题描述】:

我试图了解 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。

谁能帮我理解这种行为?

【问题讨论】:

  • "我不明白为什么复制的对象的 ID=0,而不是 1。"您的复制构造函数不会复制任何内容...
  • 我更喜欢使用复制构造函数成员初始化。所以A(const A&amp; objToCpy) : Objid(objToCpy.Objid) { cout &lt;&lt; "Copying object with id: " &lt;&lt; ObjId &lt;&lt; endl; }

标签: c++ vector constructor stl copy-constructor


【解决方案1】:

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

通过输入A(const A&amp; other) {...},您可以定义自己的复制构造函数,这意味着您可以显示每个字段是如何复制的,因此您会错过构造函数中的ObjId = other.ObjId 语句。

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

【讨论】:

  • 你是对的!当我做reserve(10)时,得到了我期望的行为。谢谢你。这意味着向量通常初始化为 1 的容量?
  • 是的,这是向量的这个特定实现的初始值。但是我不确定最初是否为 0 并且每当您添加一个元素时,它都会分配任何额外的内存。但这并不重要。
  • 离开 ObjId 未初始化会导致未定义的行为,不涉及运气
  • 实际上未定义的行为会给您带来您期望的结果是最糟糕的,因为您直到为时已晚才会发现它
【解决方案2】:

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

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


至于第二部分,我不知道发生了什么以及为什么它与第一个插入不同,唯一的例外是 ID 不同。为什么要复制2个对象

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


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

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

【讨论】:

  • 谢谢。我的错。我更改了复制构造函数(编辑了问题),但我仍然看到第二次插入的多个对象。
  • 谢谢。你说的对。当我保留()时,它起作用了。
猜你喜欢
  • 2016-03-25
  • 1970-01-01
  • 2013-10-24
  • 2013-11-18
  • 2021-12-04
  • 2016-02-11
  • 1970-01-01
  • 2019-05-14
  • 2017-12-07
相关资源
最近更新 更多