Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why &x[0]+x.size() instead of &x[x.size()]?

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?

like image 279
adroit.levees.0r Avatar asked Jan 01 '26 07:01

adroit.levees.0r


1 Answers

&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

  • UB (1): undefined behavior when creating a reference to an out-of-range-element.
  • UB (2): undefined behaviour when attempting to read the value of an out-of-range element.
  • FH: some fault handling action from the API if it is checked (e.g. throwing an exception, terminating, ...).

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.

like image 157
dfrib Avatar answered Jan 03 '26 23:01

dfrib



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!