Since &v[0]
and v.data()
provide the same way to access the underlying pointer of std::vector
, I wonder which method is the better choice in terms of stability and portability?
1 Answer
From cppreference:
"Return value
Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal to the address of the first element".
emphasis mine
For a non-empty std::vector
, both v.data()
and &v[0]
compare equal. So at this point, which one to chose would be just a matter of preference.
But if we look more carefully, we can also read that:
"Returns pointer to the underlying array serving as element storage. The pointer is such that range [data(); data()+size()) is always a valid range, even if the container is empty (data() is not dereferenceable in that case)."
emphasis mine
Which means that you could use any standard algorithm working on iterators with the returned pointer by std::vector::data()
(and its size) even if the vector is empty.
Which is not possible with taking the address of the first element since accessing a value through the subscript operator std::vector::operator[]()
for an empty vector is undefined behaviour.
Knowing that, I'd say, using std::vector::data()
is the best choice.
-
1Side note: when the vector is empty,
data()
may return a null pointer value. In this case,size()
is zero, hence,data() + size()
is well-defined and [data()
;data()+size()
) is still a valid range.– j6tCommented Dec 12, 2022 at 15:18 -
1@j6t Yes, this is exactly the point of my last paragraph.– FareanorCommented Dec 12, 2022 at 15:20
-
1@MarkB Why would it be less efficient ? Both are function calls,
data()
just basically returns the managed pointer. I would even expectdata()
to be a bit faster since no pointer arithmetic nor pointer dereferencing is required. But compiler optimizations may remove that possible difference. Anyway, if you're concerned about performances, just profile it, otherwise, it's pointless to argue about it. What is the "best" depends on the given criteria, and performances wasn't in the OP's list (but even if it was, I suspect it to be at least as efficient, or maybe even faster).– FareanorCommented Dec 12, 2022 at 15:53
std::vector
provide adata()
member function, I don't see the need to take manually the address of the first element. The only "better" choice would be for readability purposes.std::vector
will always have the subscript operator and it will always have adata()
member, so which one to chose in terms of stability and portability is not a question ^^ They are basically the same and are both required to exist by the standard.&v[0]
.data()
may or may not return anullptr
if the vector is empty. I'm not sure what they mean by "valid" range.data
is guaranteed to be valid. With that,&v[0]
can lead to UB whilestd::vector::data
is guaranteed to return something valid (though its return value is implementation defined). Seems likedata
is the right way... though you'll still want the length check in both cases.