出于测试目的,我试图创建自己的 vector 类,但我无法弄清楚 std::vector
大小缩减是如何工作的。
class A
{
A()
{ std::cout << "A constructed") << std::endl; }
~A()
{ std::cout << "A destroyed") << std::endl; }
}
main()
{
std::vector<A> vec(3, A());
vec.resize(2);
std::cout << "vector resized" << std::endl;
}
输出为
A constructed (1)
A constructed (2)
A constructed (3)
A destroyed (1)
Vector resized
A destroyed (2)
A destroyed (3)
当vec.resize(2)
被调用时,第三个元素被销毁,但是 vector 的容量仍然是3。然后当vec
被销毁时,它的所有元素包括已经销毁的元素在内的元素都应该被销毁。 std::vector
如何知道他已经销毁了该元素?如何在我的 vector 类中实现它?
最佳答案
容量和大小之间存在差异。给定 std::vector<T> v;
该 vector 已为 v.capacity()
分配了内存。元素。但仅限于第一个v.size()
地方包含构造T
对象。
所以,v.reserve(1000)
在空 vector 上不会调用任何额外的构造函数。 vec.resize(2)
在你的例子中破坏了最后一个元素和 vec[2]
现在内存中是空的,但内存仍然属于 vec
。
我认为你的分配看起来像 buffer = new T[newSize];
。不是这样std::vector
不允许的作品 Ts
没有默认构造函数。也许你没有意识到这一点,但是每当你获得一 block 内存时,它已经包含了对象,让它成为 T x;
甚至 new double[newSize];
它返回一个 double 组(尽管它们的构造函数是空的)。
在 C++ 中获取可用的未初始化内存只有一种方法,那就是分配 chars
。这是由于strict aliasing rule.还有(是|必须)一种如何在此内存上显式调用构造函数的方法,即如何在那里创建对象。该 vector 使用名为 placement new 的东西。正是这样做的。那么分配就是 buffer = new char[newSize*sizeof(T)];
它不会创建任何对象。
对象的生命周期由该放置 new 运算符和对析构函数的显式调用来管理。
emplace_back(arg1,arg2)
可以实现为 {new(buffer + size) T(arg1,arg2);++size;}
。请注意,只需执行 buffer[size]=T(arg1,arg2);
不正确,UB。 operator=
预计左侧尺寸 ( *this
) 已经存在。
如果你想用例如销毁一个对象pop_back
,你必须做
buffer[size].~T();--size;
。这是极少数应该显式调用析构函数的地方之一。
关于c++ - vector 如何在减小其大小后不破坏元素两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56908735/