[英]how is push_back implemented in STL vector?
我在一次采訪中被問到這個問題。
我回答的要點是這樣的
1) 指向當前位置的索引;
2) 必要時調整大小。
有人可以詳細說明嗎?
template< typename T >
void std::vector<T>::push_back(const T& obj)
{
this->insert(this->end(),obj);
}
當然,這本質上是實現定義的。 假設這是一個關於某人如何實現動態數組的問題,一般來說,它會是這樣的:
push_back
檢查capacity()
並確保它至少比size()
push_back
。一些 STL 實現將通過使用交換(即對於容器的容器)來消除一些副本,但在大多數情況下,這正是它的工作原理。
可能他們正在尋找的是push_back
制作被推送到vector
上的對象的副本(使用其復制構造函數)。
關於調整大小:標准說a.push_back(x)
等效於a.insert(a.end(),x)
。 insert
的定義部分說明:“如果新大小大於舊容量,則會導致重新分配。”
標准說明了函數應該做什么。 但是在大多數情況下,它們的實現方式是特定於實現的。
像這樣:
void push_back(T const& param)
{
vector temp(rbegin(), rend());
temp.push_front(param);
*this = vector(temp.rbegin(), temp.rend());
}
如果 size < capasity,那么一切似乎都沒問題,您只需在 vector 中插入 en 元素,當 size == capasity 時復雜性會增加。
用文字很容易解釋,您必須分配一個比現有數組大兩倍的新數組,並將所有這些元素復制到新分配的內存中,然后刪除舊數組並將新元素插入新數組中。 但這里有一些我認為你的面試官希望你提到的關鍵時刻。
std::vector 中的元素不保存在一個數組中,因此 std::vector[1000] 的數據成員不是長度為 1000 的 int*。元素保存在內存塊中,因此您必須在使用時考慮它復制。
其次,標准 stl 向量需要“給我一個可復制的對象,我可以插入它”,這意味着對 std::vector 的要求是 sometype 只需要有一個 copy_constructer (而不是 operator = )。 因此,當您分配 sometype 類型的新內存時,您必須考慮 sometyme 可能沒有默認的復制構造函數。 在常見的實現中,這是通過放置 new 運算符來完成的,以避免調用復制構造函數。
感謝一些評論,我正在完全修改一個非常不正確的原始答案。
根據 STL 規范,您的答案是正確的。 該向量被實現為一個動態調整大小的數組:
向量容器被實現為動態數組; 就像常規數組一樣,向量容器將它們的元素存儲在連續的存儲位置,這意味着它們的元素不僅可以使用迭代器訪問,還可以使用指向元素的常規指針的偏移量來訪問。
但與常規數組不同的是,向量中的存儲是自動處理的,允許根據需要擴展和收縮。
vector
不使用鏈表。 它使用連續內存。
如果沒有足夠的保留空間, push_back
分配一個兩倍於原始vector
的新內存塊。 通過這樣做,攤銷的運行時間是 O(1)。
面試官想要多少細節? 例如,他是否正在尋找您深入了解較低級別的細節?
除了通常的按需要調整大小以保留平均語義的 O(1) 之外,需要考慮的一些事項包括但不限於:
vector
的分配器而不是普通的基於new
的舊分配器(兩者可能相同也可能不同)? 理想情況下,這將由vector
的調整大小代碼透明地處理,但是實現肯定會有所不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.