簡體   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