2011-04-06 504 views

回答

45

由於std::vector沒有關於在前面插入元素的特殊功能,不像其他容器。每個容器提供的功能對該容器有意義。

你也許應該使用一個std::deque,這是明確在在前面背部插入。

檢查this diagram了。

7

因爲push_backpop_back是隻需要計算O(1)矢量的特殊操作。任何其他推動或流行需要O(n)

這不是一個「bug」或「怪癖」,這只是矢量容器的屬性。如果您需要快速pop_front,請考慮更改爲其他容器。

+3

具體來說,如果您需要快速的'pop_front()',考慮更改爲'std :: deque <>'。 – ildjarn 2011-04-06 09:15:44

+0

「僅需要O(1)計算」 - 在「push_back」情況下分攤爲O(1),最壞情況是由於您尚未預留空間而必須重新分配時的Theta(n)。 – 2011-04-06 09:15:47

+0

因爲用戶正在談論爆裂,所以我在本例中省略了分配。不過你是對的。 – orlp 2011-04-06 09:17:34

1

可能是因爲它對於大型載體來說會非常慢。

pop_front()對於包含1000個對象的矢量,將需要999 operator=()調用。

+0

沒有任何比'擦除(v.begin())'更慢的''。這是因爲矢量在開始時沒有特殊的屬性,反對在最後(或彈出)推動。 – orlp 2011-04-06 09:13:54

+0

@nightcracker - 確實,erase()同樣不好。我同意在vector上想要pop_front()是一種很好的「嗅覺」,你正在使用錯誤類型的容器! – Roddy 2011-04-06 09:17:00

0

但是,如果你需要一個pop_front和不在乎在向量元素的指數,你可以做一個pop_front喜歡的東西

template<typename T> 
void pop_front(std::vector<T>& vec) 
{ 
    vec.front() = vec.back(); 
    vec.pop_back(); 
} 

丹希金斯談到這也:https://youtu.be/oBbGC-sUYVA?t=2m52s

+6

這將是一個奇怪的情況,你們都做了,不關心元素的順序。因爲如果你真的不在乎,這更簡單:template void pop_front(std :: vector &v){v.pop_back(); } – MSalters 2011-04-06 12:16:08

+0

您的評論似乎對我來說不對。通過做'template void pop_front(std :: vector &v){v.pop_back(); }'你不會刪除預期的'front'元素。我的建議是「交換」「前」和「後」元素,並刪除最後一個。 – marchelbling 2014-11-02 10:40:20

+0

另外,如果你想操縱連續的內存緩衝區,可能會發生在不深入關注元素順序時使用矢量。我不爭論這是否是一個好主意,但在這個非常具體的(和指定的)情況下,它是在O(1)中做一個'pop_front'的有效方法。 – marchelbling 2014-11-02 10:45:15

13

載體通常被實現是這樣的:

struct 
{ 
    T* begin; // points to the first T in the vector 
    T* end; // points just after the last T in the vector 
    int capacity; // how many Ts of memory were allocated 
}; 

「begin」作爲「指向矢量中第一個T的指針」和「指向我們分配的所有內存的指針」的雙重任務。因此不可能通過簡單地遞增「開始」來「彈出」離開矢量前面的元素 - 這樣做,並且不再有指向您需要釋放的內存的指針。那會泄漏記憶。所以「pop_front」需要將所有的Ts從矢量的後面複製到矢量的前端,這相對較慢。所以他們決定放棄標準。

你想要的東西是這樣的:

struct 
{ 
    T* allocated; // points to all the memory we allocated 
    T* begin; // points to the first T in the vector 
    T* end; // points just after the last T in the vector 
    int capacity; // how many Ts of memory were allocated 
}; 

這一點,你可以在「pop_front」移動「開始」前後沒有遺忘的危險內存後解除分配這。爲什麼不std :: vector這樣工作?我想這是寫這個標準的人的口味問題。他們的目標可能是提供儘可能簡單的「可動態調整大小的陣列」,我認爲他們可以成功。

6

簡單。請嘗試:

vec.erase(vec.begin()); 
相關問題