Why there is no pop_front
method in C++ std::vector
?

- 378,754
- 76
- 643
- 1,055

- 18,047
- 15
- 98
- 153
8 Answers
Because a std::vector
has no particular feature regarding inserting elements at the front, unlike some other containers. The functionality provided by each container makes sense for that container.
You probably should be using a std::deque
, which is explicitly good at inserting at the front and back.
Check this diagram out.

- 378,754
- 76
- 643
- 1,055
-
2Nice diagram there but that's all black hard to comprehend – AnotherDeveloper Nov 23 '20 at 02:57
-
2This doesn't really explain why there is no pop_front() method, it only talks about insertion. How does inserting elements relate to popping elements? – Rasmus Dall Dec 17 '20 at 11:41
-
would be nice if there is way to fix the diagram. – cpchung Jan 02 '21 at 21:19
-
Note that you say "inserting", the OP asked about "pop_front()" which, if I'm correct, is deleting/removing (erasing). Not inserting. – Alexis Wilke Jun 25 '22 at 04:03
Although inefficient on large vectors, the following is equivalent to a pop_front()
for a std::vector
vec.erase(vec.begin());
As stated in other answers, std::vector
is not designed to remove the first element and will require to move/copy all remaining elements. Depending on the specific use case, it might be convenient to consider other containers.

- 19,451
- 13
- 99
- 197

- 615
- 1
- 6
- 2
vector is typically implemented something like this:
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" serves double-duty as "pointer to the first T in the vector" and "pointer to all the memory we allocated." therefore it's impossible to "pop" elements off the front of the vector by simply incrementing "begin" - do this and you no longer have a pointer to the memory you need to deallocate. that would leak memory. so a "pop_front" would need to copy all the Ts from the back of the vector to the front of the vector, and that is comparatively slow. so they decided to leave it out of the standard.
what you want is something like this:
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
};
with this, you can "pop_front" by moving "begin" forward and backward with no danger of forgetting which memory to deallocate later. why doesn't std::vector work this way? i guess it was a matter of taste among those who wrote the standard. their goal was probably to provide the simplest possible "dynamically resizeable array" they could, and i think they succeeded.
-
Not just 'taste'. Imagine all the arbitrary decisions: pushing at front exhausts the free space at head. Reallocate or just move items till there's free space at the end, if there's any at all? Pushing at end, likewise, do we move towards front or reallocate? Just moving seems wasteful, but realloc costs. Make it cyclic and enter index calculation hell? Then the capacity. Reserve(100), where do we put first element? front? center? Why? Let's pop some items, it's empty now, begin met the end, do we adjust them towards front,center,end or do nothing? Too much for configuring via type traits/etc. – quetzalcoatl Aug 14 '20 at 11:39
Because push_back
and pop_back
are special operations for a vector that require only O(1)
computation. Any other push or pop takes O(n)
.
This is not a "bug" or a "quirk", this is just a property of the vector container. If you need a fast pop_front consider changing to an other container.

- 112,504
- 36
- 218
- 315
-
5Specifically, consider changing to `std::deque<>` if you need fast `pop_front()`. – ildjarn Apr 06 '11 at 09:15
-
"requires only O(1) computation" - amortized O(1) in the case of `push_back`, worst case is Theta(n) when it has to reallocate because you haven't reserved the space. – Steve Jessop Apr 06 '11 at 09:15
-
I left out allocation in this example because the user was talking about popping. You are right though. – orlp Apr 06 '11 at 09:17
-
Naturally it would have to do a re-allocation, but why would that be O(n) in comparison to a re-allocation of 'push_back' – hiddensunset4 Apr 06 '11 at 09:26
-
@Daniel: Because `push_back` doesn't always have to re-allocate. – Lightness Races in Orbit Nov 24 '12 at 23:08
-
3Why couldn't **pop**_front be O(1)? You'd just advance the pointer to the start of the array by one element? – Jonathan. Sep 01 '16 at 11:49
-
@Jonathan. You can, but not using the same implementation as a regular vector, there is more logic there. See https://github.com/orlp/devector (implementation is not finished, but the concept is there.) – orlp Sep 01 '16 at 13:15
-
@Jonathan. Something like a deque does that, but the end result is that it has to work a bit differently if you don't want to end up with your whole computer's memory allocated but no longer used... which is why deque exists... which is why deque has `pop_front`. – Lightness Races in Orbit Jul 24 '18 at 13:12
However, if you need a pop_front and do NOT care about the index of the elements in the vector, you can do kind of a pop_front with something like
template<typename T>
void pop_front(std::vector<T>& vec)
{
vec.front() = vec.back();
vec.pop_back();
}
Dan Higgins talks about this too: https://youtu.be/oBbGC-sUYVA?t=2m52s

- 1,909
- 15
- 23
-
8It would be a weird case where you both did and did not care about the order of elements. Because if you _really_ didn't care, this is even easier: template
void pop_front(std::vector – MSalters Apr 06 '11 at 12:16& v) { v.pop_back(); } -
2Your comment seems wrong to me. By doing `template
void pop_front(std::vector – marchelbling Nov 02 '14 at 10:40& v) { v.pop_back(); }` you would not remove the expected `front` element. My suggestion is to "swap" `front` and `back` elements and remove the last one. -
1Also, using a vector when not deeply caring about elements order may happen if you want to manipulate a continuous buffer of memory. I'm not arguing wether this is a good idea or not but in this very specific (and specified) case, it is a valid way of doing a `pop_front` in O(1). – marchelbling Nov 02 '14 at 10:45
-
1
-
@marchelbling I think this is an O(2) since you have a copy + an erase. I think it is a clever way of doing it if you use a vector just to hold N items and not to hold N items in a specific order. – Alexis Wilke Jun 23 '19 at 05:23
-
@AlexisWilke indeed that's 2 O(1) operations which is equivalent to O(1) or said differently no matter the size of the vector, we can perform the `pop_front` in a constant time. – marchelbling Jun 25 '19 at 14:33
-
What MSalters referred to is that this code you proposed effectively ensures that any later other front-reading operations will actually read at the tail. Keep using this pop_front, and they keep consuming the vector from behind. Except for the very first element when pop_front was never called yet and the consumers actually got true front. So, if to follow your words and if to really "not care about the order", then why care about popping the first element from front? Just read back() and pop_back() already from the very beginning. https://en.wikipedia.org/wiki/Principle_of_least_astonishment – quetzalcoatl Aug 14 '20 at 11:26
-
Thank you for your comment. As emphasized in bold in my original answer, I'm just providing a O(1) deletion of a vector element. As your answer implies, this could actually be for any position in the vector. Again, I'm not saying this is a good idea but I just plain disagree if people assume that a vector order is necessarily important. Cache friendliness may also be important. – marchelbling Aug 16 '20 at 10:22
Probably because it would be monumentally slow for large vectors.
pop_front()
on a vector containing 1000 objects would require 999 operator=()
calls.

- 66,617
- 42
- 165
- 277
-
2Not any slower then `erase(v.begin())`. It's because vectors have no special properties for pushing in the beginning, opposed to pushing at the end (or popping). – orlp Apr 06 '11 at 09:13
-
1@nightcracker - True, erase() is equally bad. And I agree that wanting pop_front() on a vector is a good 'smell' that you're using the wrong type of container! – Roddy Apr 06 '11 at 09:17
Vector seems like a stack container, we have a stack to store data.
So we just pop_back
not to pop_front
.
If you want to pop_front
, std::list
may be a better choice for you. Cause it is a bi-direction like queue structure.

- 18,047
- 15
- 98
- 153

- 87
- 9
#define push_front(v,val) v.insert(v.begin(), 1, val);
#define pop_front(v) if(!v.empty())v.erase(v.begin());
You can directly write this and use this
push_front(vec,val);
pop_front(vec);

- 638
- 8
- 28
-
The question was not "how do I do that?" but "why is there no such function?" ... – Alexis Wilke Jun 25 '22 at 03:59
-
C called and wants its macros back... These macros have [all the usual problems](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es31-dont-use-macros-for-constants-or-functions) and blissfully ignore containers with optimized versions of the simulated operations. Please, [write a template](https://godbolt.org/z/38MsjjoKr). – Max Truxa Jan 16 '23 at 19:38