繁体   English   中英

向量减小大小后如何不破坏元素两次?

[英]How does vector not destroy element twice after reducing its size?

出于测试目的,我试图创建自己的向量类,但无法弄清楚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) ,第三个元素被销毁,但向量的容量仍为3。然后,当vec被销毁时,其所有元素(包括已销毁的元素)都应被销毁。 std::vector如何知道他已经销毁了该元素? 如何在向量类中实现它?

容量和大小之间有区别。 给定一个std::vector<T> v; 该向量已为v.capacity()元素分配了内存。 但仅在第一个v.size()位置包含构造的T对象。

因此,在空向量上的v.reserve(1000)不会调用任何其他构造函数。 您的示例中的vec.resize(2)破坏了最后一个元素,并且vec[2]现在在内存中为空,但内存仍由vec拥有。

我认为您的分配看起来像buffer = new T[newSize]; 这不是std::vector工作方式,不允许没有默认构造函数的Ts 也许您没有意识到这一点,但是每当获得一块内存时,它已经包含对象,将其设为T x; 甚至是new double[newSize]; 它返回一个双精度数组(尽管它们的构造函数为空)。

在C ++中只有一种获得可用的未初始化内存的方法,即分配chars 这是由于严格的别名规则。 还有(必须是)如何在此内存上显式调用构造函数的方法,即如何在该内存上创建对象。 向量使用称为“ 新放置”的东西来精确地做到这一点。 然后,分配就是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; pop_back buffer[size].~T();--size; 这是应显式调用析构函数的极少数地方之一。

简单的答案是,vector通常通过使用inplace运算符new和operator delete方法在内部管理构造函数和析构函数调用。

弹出元素后,将立即对其进行销毁,并且在内存仍然可用且可能仍包含一些剩余值的情况下,std :: vector本身知道哪些元素仍需要删除,因此不会再次调用析构函数。

vec.resize(2) ,第三个元素被破坏,但向量的容量仍为3。

是。 capacity是向量的内部数组可以物理容纳多少个元素。 size是该数组中实际有效的元素数。 缩小size根本不影响capacity

然后,当vec被销毁时,其所有元素,包括已经销毁的元素都应被销毁。

先前已销毁并从数组中删除的第三个元素不会再次销毁。 就像您正在思考的那样,仅破坏size的元素数目,而不破坏capacity的元素数目。

std::vector如何知道他已经销毁了该元素?

它分别跟踪sizecapacity 从数组中删除一个元素时,其后的元素将分别在数组中向下移动1个插槽,并且size会减小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM