4

How can I work with a 3 dimensional vector in C++?

vector<vector<vector<int> > > vec (1,vector<vector<int> >(1,vector <int>(1,12)));

When I try something like this

cout << vec[0][0][0]; vec[0][0][1] = 13;

everything works just fine.

The problem is that I can only change the last elements. If I try accessing the first and second element, like this

vec[0][1][0] = 13;

or this

vec.push_back(vector<vector<int > >());
vec[0].push_back(vector<int>()); 
v[1][0].push_back(13);

my program crashes.

How can I add and access elements in a 3d vector?

4
  • You've specified the size in i and j to be 1, and because in C++ vectors/arrays are 0-based, there is no index 1 defined for them.
    – triple_r
    Commented Mar 27, 2015 at 16:38
  • At the begining I have 1x1x1 vector. So how can I push elements. using push_back() ? For example I have 1x1x1 and I want to add v[1][1][0] = 2 ?
    – NonSense
    Commented Mar 27, 2015 at 17:59
  • You can make a 2D vector and push it. For example: vector<vector<int>> tmp(2, vector<int>({2})); and then vec.push_back(tmp);. So the first one makes a 2D array of size 2x1 (so you can have a value for [1][0]). You can combine the two lines, or even split it into three lines (make lots of 1D arrays, push them into a 2D array, and push the resulting 2D array into the 3D array).
    – triple_r
    Commented Mar 27, 2015 at 20:06
  • In my opinion doing multidimensional arrays with std::vector is absolutely horrible. Boost Multidimensional Array is better. I'm not sure why something like it didn't make it into the standard (or did it?).
    – Robinson
    Commented Mar 27, 2015 at 22:17

3 Answers 3

4

I would never do vector<vector<vector<int> > > as in this way you have many allocations what could be expensive. I would simply use vector<int> with smart indexing (e.g.: see below). If you will work with double based matrices, in this way intel MKL or any other BLAS library easily could be used.

Its price is increased complexity when matrix sizes are changed, but you could win many in performance.

Useful link: C++ FAQ.

static int const M = 16;
static int const N = 16;
static int const P = 16;

inline int& set_elem(vector<int>& m_, size_t i_, size_t j_, size_t k_)
{
    // you could check indexes here e.g.: assert in debug mode
    return m_[i_*N*P + j_*P + k_];
}
inline const int& get_elem(const vector<int>& m_, size_t i_, size_t j_, size_t k_)
{
    // you could check indexes here e.g.: assert in debug mode
    return m_[i_*N*P + j_*P + k_];
}

vector<int> matrix(M*N*P, 0);
set_elem(matrix, 0, 0, 1) = 5;
2
vector<vector<vector<int> > > vec (1,vector<vector<int> >(1,vector <int>(1,12)));
cout << vec[0][0][0]; vec[0][0][1] = 13;

evething is OK.

You are mistaken. Everything is not OK. The vector vec[0][0] has only one element and thus vec[0][0][1] is out of bounds and therefore the assignment has undefined behaviour. You have the same problem with vec[0][1][0] = 13; and v[1][0].push_back(13)

You can fix that by accessing only indices that exist in your vectors. If you want more than one element, then either construct the vectors with more elements initially, or push them after construction.

At the begining I have 1x1x1 vector. So how can I push elements. using push_back() ? For example I have 1x1x1 and I want to add v[1][1][0] = 2 ?

If you for some reason want to start with 1x1x1 vector of vectors of vectors of ints and want to access v[1][1][0], here is example code to add the v[1][1][0] element with minimal changes to the original vector:

 // vector of ints that contains one element, 2
 // this will vector eventually be the v[1][1] and the integer element will be v[1][1][0]
 // since we initialize the integer as 2, there's no need to assign it later though
 vector<int> vi(1, 2);

 // vector of vectors that contains one default constructed vector
 // vvi will eventually be the v[1] element and the default constructed vector will be v[1][0]
 vector<vector<int>> vvi(1); 

 // push vi into vvi, making it vvi[1] and eventually v[1][1]
 vvi.push_back(vi);

 // push vvi into v, making it v[1]
 v.push_back(vvi);
3
  • At the begining I have 1x1x1 vector. So how can I push elements. using push_back() ? For example I have 1x1x1 and I want to add v[1][1][0] = 2 ?
    – NonSense
    Commented Mar 27, 2015 at 17:59
  • @NonSense In order to access the element v[1][1][0], the outermost vector (v, which is a vector of vectors of vectors) must have at least two elements and the second element of v (i.e. v[1], which is a vector of vectors) must also have 2 elements. The second element of that vector (i.e. v[1][1], which is a vector of ints) must have at least one element, which would be the v[1][1][0] element.
    – eerorika
    Commented Mar 27, 2015 at 21:35
  • @NonSense I added code to push the v[1][1][0] element with minimal changes to the rest of the vectors.
    – eerorika
    Commented Mar 27, 2015 at 22:01
2

What you have,

vector<vector<vector<int> > > vec (1,vector<vector<int> >(1,vector <int>(1,12)));

creates 1 x 1 x 1 matrix with the value of the only element set to 12.

To create something that is analogous to a M x N x P matrix, you need to use:

vector<vector<vector<int> > > vec (M,vector<vector<int> >(N,vector <int>(P,x)));

That will create an M x N x P matrix with the value of each element set to x.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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