18

Is the memory in std::array contiguous? Is the following valid/good practice?

std::array<type1,Num> arr = //initialize value
type1 * ptr = &arr[0];

Could I then pass ptr to functions expecting a c-style array?

Xeo
  • 129,499
  • 52
  • 291
  • 397
Riley
  • 982
  • 1
  • 7
  • 19

2 Answers2

32

Yes, it is contiguous, as it is basically (and actually) a type arr[10];, but with STL like interface. It also doesn't decay to a pointer on the slightest provocation.

You can safely pass &arr[0] to a function expecting a C-style array, that's the design goal of it. To use it with the STL algorithms however, just use the begin and end functions:

// either members
std::sort(arr.begin(), arr.end());
// or free from <iterator>
std::sort(std::begin(arr), std::end(arr));

For the language lawyer part, §23.3.2.1 [array.overview] p1:

The header <array> defines a class template for storing fixed-size sequences of objects. An array supports random access iterators. An instance of array<T, N> stores N elements of type T, so that size() == N is an invariant. The elements of an array are stored contiguously, meaning that if a is an array<T, N> then it obeys the identity &a[n] == &a[0] + n for all 0 <= n < N.

And §23.3.2.1 [array.overview] p2:

An array is an aggregate (8.5.1) that can be initialized with the syntax

  • array<T, N> a = { initializer-list };

Also, in p3, listing the members of std::array:

T elems[N]; // exposition only
[ Note: The member variable elems is shown for exposition only, to emphasize that array is a class aggregate. The name elems is not part of array’s interface. —end note ]

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • The standard explicitly states that `std::vector` shall have contiguous memory allocation, Similar is the case with std::array? – Alok Save Jul 09 '11 at 05:23
  • @Als: First, I get notified of comments to my answer anyways, second, yes. :) – Xeo Jul 09 '11 at 05:27
  • Just out of curiosity, does that quote from the standard explicitly require that `std::array<_T, _N>` be implemented under-the-hood as `_T arr[_N]`?? Not that it's a good idea, but what's to stop me having a `std::array` class that allocates a correctly sized `std::vector` behind the scenes and prevents any resizing?? As I said, I'm NOT suggesting this would be a good idea. – Darren Engwirda Jul 09 '11 at 05:37
  • 1
    @Darren The requirement that `std::array` be an aggregate. – Luc Danton Jul 09 '11 at 05:50
  • @Xeo, Luc: good, looks like they've got all bases covered... :) – Darren Engwirda Jul 09 '11 at 06:12
  • Why use `arr.begin()` and `arr.end()` in preference to `begin(arr)` and `end(arr)`? I find it slightly amusing that C++0x finally adds a container-style interface to an automatic array, at the same time as finally introducing a concept of a single object that represents a range, so that we no longer need an array to have a container-style interface ;-) – Steve Jessop Jul 09 '11 at 09:32
  • @Steve: I do so, because *I can*. ;) – Xeo Jul 09 '11 at 12:05
-1

Yes the memory of std::array is contiguous. On VC10, it is declared as:

template<class _Ty,
    size_t _Size>
    class array
    { // fixed size array of values
                ... 
         _Ty _Elems[_Size == 0 ? 1 : _Size];
    };

Where _Elemes is nothing but a simple array of given type.

Ajay
  • 18,086
  • 12
  • 59
  • 105
  • 3
    This is merely one implementation of `std::array`. Your answer is correct, but your justification is invalid. Other implementations could write the class differently. The reason they can't is because it would violate the specification. You forgot to mention that. – Cody Gray - on strike Jul 09 '11 at 10:55
  • May be, buy GNU implementation uses same approach: http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01741.html – Ajay Jul 19 '11 at 09:21