3

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?

6
  • 3
    Since std::vector provide a data() 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 a data() 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.
    – Fareanor
    Commented Dec 12, 2022 at 12:59
  • 3
    Hmm. From cppreference: 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). Not sure that holds when using &v[0]. Commented Dec 12, 2022 at 13:05
  • 1
    @AdrianMole But if you look further they mention that data() may or may not return a nullptr if the vector is empty. I'm not sure what they mean by "valid" range.
    – Fareanor
    Commented Dec 12, 2022 at 13:10
  • 1
    @Fareanor Some discussion is here: stackoverflow.com/q/25419851/580083. Commented Dec 12, 2022 at 13:11
  • 5
    TIL that data is guaranteed to be valid. With that, &v[0] can lead to UB while std::vector::data is guaranteed to return something valid (though its return value is implementation defined). Seems like data is the right way... though you'll still want the length check in both cases.
    – erip
    Commented Dec 12, 2022 at 13:15

1 Answer 1

14

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.

3
  • 1
    Side 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.
    – j6t
    Commented Dec 12, 2022 at 15:18
  • 1
    @j6t Yes, this is exactly the point of my last paragraph.
    – Fareanor
    Commented 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 expect data() 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).
    – Fareanor
    Commented Dec 12, 2022 at 15:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.