理解向向量中插入对象时的构造、复制和销毁
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
语句。
第二种情况发生是因为您的矢量正在调整大小,因此它必须将所有元素从旧存储复制到新的、更大的、也适合新元素的存储。
我想了解 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
语句。
第二种情况发生是因为您的矢量正在调整大小,因此它必须将所有元素从旧存储复制到新的、更大的、也适合新元素的存储。