A TR1 Tutorial: Class std::tr1::array

Not long ago, Microsoft released VisualC++ 2008 Feature Pack, a package with extensions to MFC 9.0 and an implementation of TR1 (a document specifying extensions to STL, but not yet standardized). These additions are grouped in 10 new headers under the namespace std::tr1. In this article, I will introduce the header and class array.

The array Type

An array is a sequence of a fixed length (N) of the same type. Once defined, the size of an array cannot be modified. In the following examples, I will use the type int for the elements of the arrays, but it should be obvious, because array is a template class, that any type can be used.

Creating Arrays

An array can be created an initialized in several ways:

  • Using the default constructor (without parameters)
  • // an array with 3 uninitialized elements
    std::tr1::array<int, 3> arr;
    
  • Creating and initializing with an aggregate initializer
  • // an array with 3 initialized elements
    std::tr1::array<int, 3> arr = {1, 2, 3};
    
  • Using the copy constructor
  • // an array with 3 initialized elements
    std::tr1::array<int, 3> arr1 = {1, 2, 3};
    
    // making copies of the array
    std::tr1::array<int, 3> arr2(arr1);
    std::tr1::array<int, 3> arr3 = arr2;
    

A class array has a method called assign() that sets all the elements of an array to the specified value.

// an array with 3 uninitialized elements
std::tr1::array<int, 3> arr3;

// set all the elements to 1
arr3.assign(1);

Size of an Array

There are two methods, size() and max_size(), that return the number of elements of an array. There is no difference between the two. Moreover, the method empty() indicates whether an array has no elements (in other words, its dimension is 0).

std::tr1::array<int, 3> arr_d3;
std::cout << "size  = " << arr_d3.size()  << std::endl;
std::cout << "empty = " << std::boolalpha << arr_d3.empty()
          << std::endl;

std::tr1::array<int, 0> arr_d0;
std::cout << "size  = " << arr_d0.size()  << std::endl;
std::cout << "empty = " << std::boolalpha << arr_d0.empty()
          << std::endl;
size  = 3
empty = false
size  = 0
empty = true

Iterating and Accessing Elements

You can iterate over an array just like any other STL container.

  • Using direct iterators (head to tail)
  • std::tr1::array<int, 3> arr1 = {1, 2, 3};
    for(std::tr1::array<int, 3>::const_iterator it =
       arr1.begin();
       it != arr1.end(); 
       ++it)
    {
       std::cout << *it << " ";
    }
    std::cout << std::endl;
    
    1 2 3
  • Reverse (tail to head):
  • for(std::tr1::array<int, 3>::const_reverse_iterator rit =
       arr1.rbegin();
       rit != arr1.rend();
       ++rit)
    {
       std::cout << *rit << " ";
    }
    std::cout << std::endl;
    
    3 2 1

Another way to access elements of an array is by using operator[] or method at(). The difference between the two is that method at() throws an exception of type std::out_of_range if the index is not valid.

std::tr1::array<int, 3> arr = {1, 2, 3};

for(size_t i = 0; i < arr.size(); ++i)
{
   std::cout << arr[i] << " ";
}
std::cout << std::endl;
1 2 3
std::tr1::array<int, 3> arr = {1, 2, 3};
for(size_t i = 0; i < 10; ++i)
{
   try
   {
      std::cout << arr2.at(i) << " ";
   }
   catch(std::out_of_range& ex)
   {
      std::cout << ex.what() << std::endl;
   }
}
std::cout << std::endl;
1 2 3 invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript

A TR1 Tutorial: Class std::tr1::array

Another method to access the elements is represented by the function get() in the header <array>.

std::tr1::array<int, 3> arr = {1, 2, 3};

std::cout << "arr[0] = " << std::tr1::get<0>(arr) << std::endl;
std::cout << "arr[1] = " << std::tr1::get<1>(arr) << std::endl;
std::cout << "arr[2] = " << std::tr1::get<2>(arr) << std::endl;
arr[0] = 1
arr[1] = 2
arr[2] = 3

Moreover, the class array has two methods, front() and back(), that return a reference to the first and last elements of an array (must not be empty).

std::tr1::array<int, 3> arr = {1, 2, 3};

std::cout << "head: " << arr.front() << std::endl;
std::cout << "tail: " << arr.back() << std::endl;
head: 1
tail: 3

Using an Array with C-Like Functions

You can use an array with C-like function that takes as an argument a T*. Method data() returns the address of the first element in the array.

void init(int* arr, size_t length)
{
   for(size_t i = 0; i < length; ++i)
   {
      arr[i] = (i+1)*(i+1);
   }
}

void print(const int* arr, size_t length)
{
   for(size_t i = 0; i > length; ++i)
   {
      std::cout << arr[i] << " ";
   }
   std::cout << std::endl;
}
// an array of 3 uninitialized elements
std::tr1::array<int, 3> arr;

// initialize the array
init(&arr[0], arr.size());

// print the elements of the array
print(arr.data(), arr.size());
1 4 9

The above example shows the two ways (data() and &arr[0]) the elements of an array can be passed as arguments to C-like functions.

Using an Array with STL Algorithms

Like any other STL container, an array can be used with the STL algorithms.

int make_double(int val)
{
   return val * 2;
}

std::tr1::array<int, 3> arr = {1, 2, 3};

std::transform(arr.begin(), arr.end(), arr.begin(), make_double);

for(std::tr1::array<int, 3>::reverse_iterator it = arr.begin();
   it != arr.end();
   ++it)
{
   std::cout << *it << " ";
}
std::cout << std::endl;
2 4 6

Swapping

The content of two arrays can be swapped by using either the method swap() from array class, or the function with the same name from the header <array>.

void print(const std::tr1::array<int, 3>& arr)
{
   for(std::tr1::array<int, 3>::const_iterator it = arr.begin(); 
       it != arr.end(); 
       ++it)
   {
      std::cout << *it << " ";
   }
   std::cout << std::endl;
}

std::tr1::array<int, 3> arr1 = {1, 2, 3};
std::tr1::array<int, 3> arr2 = {4, 5, 6};

std::cout << "before swapping" << std::endl;
print(arr1);
print(arr2);

std::cout << "after first swapping" << std::endl;
arr1.swap(arr2);
print(arr1);
print(arr2);

std::cout << "after second swapping" << std::endl;
std::tr1::swap(arr1, arr2);
print(arr1);
print(arr2);
before swapping
1 2 3
4 5 6
after first swapping
4 5 6
1 2 3
after second swapping
1 2 3
4 5 6

Debugger Support

The VC++ debugger offers the same kind of support as for the other STL containers. You can vizualize the content of the array in human-friendly manner as shown in the following image.

[arraysdebugger.png]

Conclusions

array is a useful class when you need a sequence of a fixed size, especially for those used to code in the C++ style, not the C style. Before TR1, the only possibility was the use of a vector; that has the major problem that it could be resized. Now, array provides functionality for such fixed sequences.



About the Author

Marius Bancila

Marius Bancila is a Microsoft MVP for VC++. He works as a software developer for a Norwegian-based company. He is mainly focused on building desktop applications with MFC and VC#. He keeps a blog at www.mariusbancila.ro/blog, focused on Windows programming. He is the co-founder of codexpert.ro, a community for Romanian C++/VC++ programmers.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 20, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds