4 ms·
I suppose it causes an integer underflow and tryies to in-place destruct in an empty buffer? The std::vector class is somewhat inconsistent about safety and ma
by st_goliath 4y ago
I suppose it causes an integer underflow and tryies to in-place destruct in an empty buffer?
The std::vector class is somewhat inconsistent about safety and maps a lot of it's operations directly to unsafe, raw array access. The C++ STL contains a lot of historical baggage and design inconsistencies.
For instance, while std::vector has an `at(index)` method, that does proper bounds checking and throws an exception if the index is out of range, it also has an overloaded `operator []` that mimics array syntax that will happily write out of bounds, trashing the heap.
- gpderetta 4y agoSTL was designed to have no overhead over the corresponding C code. If push_back (and all other functions) had an extra check even when it was guaranteed non-empty by construction, it would have been a non-starter for many users. Consider that it took many years for compilers to reach the near zero overhead for STL as it is, removing precondition checks would have been beyond the ability of many compilers 20 years ago, and it still challenging today. Of course the actual overhead went down since and today we expect code to be more robust by default, but the original design principles were different. If you want safety by default, check your compiler documentation and compile with lightweight assertions enabled even in release builds.
- simiones 4y agoThis makes sense for std::vector::operator[], but not for pop_back and push_back - as those don't have any equivalent for a C array. Instead, it's just another example of C++ optimizing for speed as opposed to correctness.
- gpderetta 4y agoThe equivalent C code is what you would write inline to do a pop_back on an array. You can't write a fast pop_back for std::vector if it didn't provide one by default as the fields you would need to manipulate are private. And yes, it is indeed an instance of C++ optimizing for speed, which is exactly what I said.
- simiones 4y agostd::vector exposes the exact same API as a C array, in terms of being able to write an external pop_back() function, since C arrays only expose the ability to access a particular element - no more, no less (and std::vector::resize() can be used instead of realloc() if that is desired).
- gpderetta 4y agoThe equivalent of of std vector is an array+size+capacity field. pop_back would litterally be capacity--. resize has overhead as it needs to handle resize up as well as down.
- simiones 4y agoSure, and I'm saying in C you could write: struct stack { int[] elems; int len, cap; }; int pop_back(struct stack *x) { elem = x->elems[x->len - 1]; x->len--; return elem; } while in C++ you could have written: struct stack { std::vector elems; int len, cap; }; int pop_back(stack& x) { elem = x[x.len - 1]; x.len--; return elem; } If you wanted C-style speed, with no safety.
- zabzonk 4y agothat is not valid c. and in valid c++ (which this isn't) you would not need those two integer values.
- tsimionescu 4y agoThere are some minor syntax errors - I should have written `int *elems` instead of `int[] elems`, and I forgot to declare `int elem` instead. Apart from these nitpicks, it's completely valid C. As for C++, the <int> is missing on the std::vector, the elem variable is again not declared, and instead of x[...] it should have been x.elems[...]. Otherwise working valid C++. And yes, the `cap` is not really required, we could use x.elems.size() instead.