I'm reading A Tour of C++ (2nd edition) and I came across this code (6.2 Parameterized Types):
template<typename T>
T* end(Vector<T>& x)
{
return x.size() ? &x[0]+x.size() : nullptr; // pointer to one-past-last element
}
I don't understand why we use &x[0]+x.size() instead of &x[x.size()]. Does it mean that we take the address of the first element in x and just add to that number x.size() bytes?
&x[x.size()] would result in (attempting to) take the address of x[x.size()]. However x[x.size()] attempts to access an out of bound element; depending on the API of Vector<T>::operator[] for the particular T, a number of bad things could happen:
| Vector<T>::operator[] semantics |
| ======================================= |
| return\ contr | | |
| type \ -act | unchecked | checked |
| --------------------------------------- |
| reference | UB (1) | FH |
| value | UB (2) | FH |
| --------------------------------------- |
with
For std::vector, as an example, you would run into UB (1) as its operator[] is unchecked and returns a reference type.
Whilst you may perform pointer arithmetics to compute a pointer to one-past-last (semantically end()) of a buffer, you may not dereference a one-past-last pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With