Actually, the main problem with &buffer[0]
(note the absence of parantheses) isn't that it isn't really pretty. (That's subjective anyway. I remember finding buffer.begin(), buffer.end()
not pretty at all, when I first learned to use the STL.)
The main problem is that it invokes undefined behavior whenever buffer
is empty -- and most code never checks for that. That's why I put these into my toolbox:
template <class T, class TAl>
inline T* begin_ptr(std::vector<T,TAl>& v)
{return v.empty() ? NULL : &v[0];}
template <class T, class TAl>
inline const T* begin_ptr(const std::vector<T,TAl>& v)
{return v.empty() ? NULL : &v[0];}
template <class T, class TAl>
inline T* end_ptr(std::vector<T,TAl>& v)
{return v.empty() ? NULL : (begin_ptr(v) + v.size());}
template <class T, class TAl>
inline const T* end_ptr(const std::vector<T,TAl>& v)
{return v.empty() ? NULL : (begin_ptr(v) + v.size());}
Using these, you can write your code as
callFunction( begin_ptr(buffer), buffer.size() );
Whether begin_ptr(buffer)
is prettier than &buffer[0]
is left for you to decide. However, given that NULL
should be checked for every pointer function argument, it definitely is more safe.