Multi-Dimensional Arrays

This is another topic we get asked quite a bit.
- How do I do a 2D/3D Array?

When I also started working with multi-dimensional arrays I found it hard to find the answers I wanted too. So I'll post up some info that will hopefully help other people. I'll go over both of the 2 major methods (Vector vs Pointer).

Vector based multi-dimensional arrays
Vectors are a STL container that allow you to store pretty much anything in them. When used correctly they can be very powerful containers.

They provide an added benefit that they will automatically remove the memory they use when they go out of scope. This means that objects stored within a vector do not need to be de-allocated (but pointers to objects do).

You can also do some interesting things with dynamic multi-dimensional arrays with vectors. For example, if you only allocate the first dimension, then use the .push_back() to add records to the 2nd dimension it's no longer a grid, but an array with a dynamically sized 2nd dimension (much like a street of buildings each with a different amount of floors). This functionality can be achieved using pointers, but is much harder to do.

Pointer based multi-dimensional arrays
Pointer based multi-dimensional arrays provide you with a more raw access to the objects. The benefits can be added speed and you can apply custom optimizations to them.

Note: There are ways you can optimize this by combining the 2 dimensions into a single dimension (HEIGHTxWIDTH). I leave the discussion of this out, as it's a more advanced topic for people already familiar with this topic.

One final thing to note. When creating dynamic arrays with your own object types, you cannot overload the constructor. The ISO standard forbids this, and you must initialize the values on the objects later. All objects allocated into arrays must utilize the default constructor.

The above code snippets should compile on both Windows and Linux with no problems.

Recommendations
Unless your application has an extreme need to be highly optimized, and you are quite proficient at C++ memory management, you will want to use the vector based approach. This method is a lot easier to manage, especially if you are just learning C++.

@cstrieder: I wouldn't recommend returning the vector as it will cost you dearly. you'd have to build a vector within the function and return it by value resulting in a copy after building the vector. Multi-Dimensional arrays can get very large depending on their size and number of dimensions. I would recommend passing an inout parameter to the function as a reference and then filling it for the caller. The function would have a void return type. First, create a typedef for the type so that you don't have to retype so much.

typedef std::vector<vector<double> > MatrixArrayType;

Declare the function like so. Notice that you don't need to pass cols and lines parameters anymore because the caller could simply build the inout parameter to the correct initial size. Moreover, it is not good for Matrix_Read to assume things about the file. You need to take into consideration that the contents of the file could cause it to grow. void matrix_read(istream &iFile, MatrixArrayType& theMatrix);

@zaita: I think that this is a nice article. I only have 2 minor critiques of it.

First, the following statement is not entirely true. I see your point but it is worded incorrectly.

One final thing to note. When creating dynamic arrays with your own object types, you cannot overload the constructor. The ISO standard forbids this, and you must initialize the values on the objects later. All objects allocated into arrays must utilize the default constructor.

You can overload the constructor provided that you define the default constructor or provide a constructor that can be invoked without any arguments. Take a look at this example. It compiles just fine. The constructor has default values so a point can be constructed without any user supplied arguments.

The only other suggestion I had was to provide a 3rd section on non-dynamic multi-dimensional arrays. Perhaps the intent was to show how dynamic arrays are created but based on the title I thought it was about multi-dimensional arrays in general. They don't have to be dynamic at all.

"The Boost Multidimensional Array Library provides a class template for multidimensional arrays, as well as semantically equivalent adaptors for arrays of contiguous data. The classes in this library implement a common interface, formalized as a generic programming concept. The interface design is in line with the precedent set by the C++ Standard Library containers. Boost MultiArray is a more efficient and convenient way to express N-dimensional arrays than existing alternatives (especially the std::vector<std::vector<...>> formulation of N-dimensional arrays). The arrays provided by the library may be accessed using the familiar syntax of native C++ arrays. Additional features, such as resizing, reshaping, and creating views are available (and described below). "