36

When you want access a std::vector as a C array you can choose from at least four different ways, as you can see in this example:

#include <iostream>
#include <vector>

using namespace std;

int main() {
  std::vector<int> vec;
  vec.push_back(1);
  vec.push_back(2);
  vec.push_back(42);
  vec.push_back(24024);
  {
    int* arr = vec.data();
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
  {
    int* arr = &vec.front();
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
  {
    int* arr = &vec[0];
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
  {
    int* arr = &vec.at(0);
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
}

The one I've found in most cases is the &vec[0]. I think it's the least elegant, so... why is it the most used? Is it more efficient or more compatible? I can't find lot of documentation about data().

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
Alessandro Pezzato
  • 8,603
  • 5
  • 45
  • 63
  • 1
    `data()` *may* be regarded incompatible in the sense that it's C++11 (which explains the scarce documentation, as major documentation sources are just catching up with new features), though time will surely make this incompatibility vanish and then it's the definite way to go. – Christian Rau May 24 '12 at 15:25

5 Answers5

25

data() is brand new to C++11, that's why you don't see it as often. The idea of using &vec.front() never even occurred to me, probably because I use operator[] alot more often than front() (almost never). I imagine it's the same for other people.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • @MooingDuck: Only for const vectors, [I think](http://en.cppreference.com/w/cpp/container/vector/data). I'll test it now. – Benjamin Lindley May 24 '12 at 15:09
  • 10
    @MooingDuck No. It was added exactly so people wouldn't have to write: `v.empty()?NULL:&v[0]`. – bames53 May 24 '12 at 15:09
  • @MooingDuck my example compiles and runs, and as you can see data() returns a non const pointer. – Alessandro Pezzato May 24 '12 at 15:10
  • So `data()` is not compatible with old C++? – Alessandro Pezzato May 24 '12 at 15:14
  • @AlessandroPezzato: Correct, though I'm having a hard time proving it, as GCC appears to support it even when not in C++11 mode. – Benjamin Lindley May 24 '12 at 15:21
  • @BenjaminLindley I'm using gcc 4.4 with standard C++ and `data()` works fine. – Alessandro Pezzato May 24 '12 at 15:26
  • @AlessandroPezzato: Yeah, that's why I said I'm having a hard time proving it. It may have been an early adopted extension. I don't have a C++03 official standard on hand. But I can refer to old, semi-reliable sources where `data()` doesn't appear, like [here](http://cplusplus.com/reference/stl/vector/) ,or [this book.](http://www.amazon.com/The-Complete-Reference-4th-Edition/dp/0072226803/ref=sr_1_1?ie=UTF8&qid=1337873363&sr=8-1) – Benjamin Lindley May 24 '12 at 15:29
  • 1
    `data()` has been a non-standard extention to vector in libstdc++ for a while. Now it's part of the standard as of C++11 – Dave S May 24 '12 at 15:29
23

If you're using C++11, then using data() is definitely preferable. In particular, if the vector is empty, then using either of the other two options yields undefined behavior! If you're not using C++11, and the vector may be empty, then be sure to check that condition.

Edward Loper
  • 15,374
  • 7
  • 43
  • 52
6

Using &vec[0] is the most common although, I agree, does look a little odd. One thing to keep in mind for the future. If your vector happens to be a vector of objects whose class overloads the operator&(), realize that this will cause strange behavior if you call &vec[0].

This will not get the starting address of the first item in the internal contiguous array of objects, it will return whatever vec[0].operator&() would return. Most if not all of the time, that's not the address you're looking for (Jedi hand wave).

A good example of this is ATL's CComPtr. It overloads operator&() so storing it in a vector can be problematic. To get around this, ATL has a CAdapt template class which can be used to hide the operator&() on CComPtr

cppguy
  • 3,611
  • 2
  • 21
  • 36
1

Before C++11's std::array I would say that std::vector was the most common container to be used instead of the C-style array. The [] operator usually implies constant time access, (which is what std::vector is all about), and so most coders usually choose this style to reflect array-like access and behavior.

Eitan T
  • 32,660
  • 14
  • 72
  • 109
1

data() has been part of std::string for some time now so you might read-up on that. I've found the data() implementation in std::vector to be similar. I occasionally use data() to treat a std::string as an array of raw bytes.