exception with loop

Pages: 12
technologist wrote:
How do I know what dimensions and subsequent memory load wont cause overflow.

Trial and error is probably the best way. Keep increasing the memory used from a "this works" amount to one the OS can't allocate.

Personally I'd use a C++ container so all the messy memory management is done for me. All I have to deal with then is if my app successfully gets the memory allocated I want. Properly allocating a 3D array on the heap can be very easy to screw up IMO.

The syntax of creating for instance a 3D vector can be a bit more to type than a 3D regular array, the ease of it being run-time dynamic without manual memory management over-comes that issue IMO:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>

int main()
{
   std::cout << "Creating a 3-dimensional vector, enter row size: ";
   size_t row { };
   std::cin >> row;

   std::cout << "Enter column size: ";
   size_t col { };
   std::cin >> col;

   std::cout << "Enter depth size: ";
   size_t depth { };
   std::cin >> depth;

   // create a 3 dimensional int vector with known dimensions
   using std::vector;
   vector<vector<vector<int>>> vec(row, vector<vector<int>>(col, vector<int>(depth, 0)));
}
One nitpick, a multi-dimensional vector is probably a whole lot slower and cumbersome because it's not a simple, contiguous array; for a 3D vector, you have n^2 array allocations instead of just one. I've done some stuff with vectors of vectors in the past for image processing, and it can be like a magnitude slower depending on how it's being used (probably because of caching). Would be nice if C++ automatically did the math for 1D -> nD vector offsets, but using a single vector is still probably your best bet.
Last edited on
If you could put the multidimensional array on a linear single contiguous array I would like to know how to do that. It makes more sense and reduces the search overhead. But isn't that saying then this array never belonged in a multi dimensional array in the first place if it can be in a single?

Hi George P. I'm going to try the 3 dimensional vector. I'll compare this with one lastchance posted just for giggles. I'll try to find a decent algo to see which one goes quickest.
But isn't that saying then this array never belonged in a multi dimensional array in the first place if it can be in a single?
Apologies to the thread if this is going off into a tangent, but any N-dimensional, uniform set of data can be flattened to a lower dimension.

For example, in the 2D case, instead of
1
2
int arr[height][width];
arr[y][x] = value(x, y);
you might have something like:

1
2
int arr[height * width];
arr[y * width + x] = value(x, y);

where x and y go from [0, to width-1] and [0, height-1], respectively.

The 3D case becomes more complicated, and I usually don't have to work with 3D grids, but the same principle applies.
x + (y * maxX) + (z * maxX * maxY);
https://stackoverflow.com/questions/26162501/how-do-you-flatten-a-3d-array

With multi-dimensional C-arrays, this math is done for you, but not for containers like std::array/vector.
Actually -- there might be something you could do with a clever pointer cast to emulate the same behavior, but I'm hesitant to go down that path.
Last edited on
Personally I'd never create a 3D (or more) vector*, the most I'd do is 2D. Or do simulated xD in 1D as you point out.

I normally don't work with gobs and gobs of data on the order of multi-GBs that have be in memory at any one time. So performance hits wouldn't be noticeable for the most part.

YMMV.

*Displaying a 1D/2D vector/array as if it were a native C++ type is IMO easy to achieve:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <vector>
#include <numeric>

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v);

int main()
{
   // creating a sized vector
   std::vector<int> a1DVec(5);

   std::cout << "Displaying a sized 1D vector:\n";
   std::cout << a1DVec.size() << '\n' << a1DVec << "\n\n";

   std::cout << "Creating a 2-dimensional vector, enter row size: ";
   int row_size;
   std::cin >> row_size;

   std::cout << "Enter column size: ";
   int col_size;
   std::cin >> col_size;

   std::cout << "\n";

   std::vector<std::vector<int>> a2DVec(row_size, std::vector<int>(col_size));

   // initialize the vector with some values other than zero
   int start = 101;
   int offset = 100;

   // step through each row and fill the row vector with some values
   for (auto& itr : a2DVec)
   {
      std::iota(itr.begin(), itr.end(), start);
      start += offset;
   }
   std::cout << "Displaying the filled 2D vector:\n";
   std::cout << a2DVec;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   for (auto const& x : v)
   {
      os << x << ' ';
   }
   return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for (auto const& x : v)
   {
      os << x << '\n';
   }
   return os;
}
Displaying a sized 1D vector:
5
0 0 0 0 0

Creating a 2-dimensional vector, enter row size: 4
Enter column size: 5

Displaying the filled 2D vector:
101 102 103 104 105
201 202 203 204 205
301 302 303 304 305
401 402 403 404 405

Ramping up to 3D requires manual looping -- I haven't found a way to automate -- and the looping be done "out of order" to get IMO the proper 3D display.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <vector>
#include <numeric>

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v);

int main()
{
   std::cout << "Creating a 3-dimensional vector, enter row size: ";
   size_t NX { };
   std::cin >> NX;

   std::cout << "Enter column size: ";
   size_t NY { };
   std::cin >> NY;

   std::cout << "Enter depth size: ";
   size_t NZ { };
   std::cin >> NZ;
   std::cout << '\n';

   // create a 3 dimensional int vector with known dimensions
   using std::vector;
   vector<vector<vector<int>>> vec(NX, vector<vector<int>>(NY, vector<int>(NZ, 0)));

   // initialize the vector with some values
   for (int X { }; X < vec.size(); ++X)
   {
      for (int Y { }; Y < NY; ++Y)
      {
         for (int Z { }; Z < NZ; ++Z)
         {
            vec[X][Y][Z] = (((X + 1) * 100) + ((Y + 1) * 10) + Z + 1);
         }
      }
   }

   // display the vector
   for (int Z { }; Z < NZ; ++Z)
   {
      for (int X { }; X < NX; ++X)
      {
         for (int Y { }; Y < NY; ++Y)
         {
            std::cout << vec[X][Y][Z] << ' ';
         }
         std::cout << '\n';
      }
      std::cout << '\n';
   }

   // let't try that again
   
   std::cout << "Displaying a 2D vector:\n" << vec;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   for (auto const& x : v)
   {
      os << x << ' ';
   }
   return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for (auto const& x : v)
   {
      os << x << '\n';
   }
   return os;
}
Creating a 3-dimensional vector, enter row size: 3
Enter column size: 4
Enter depth size: 2

111 121 131 141
211 221 231 241
311 321 331 341

112 122 132 142
212 222 232 242
312 322 332 342

Displaying a 2D vector:
111 112
121 122
131 132
141 142

211 212
221 222
231 232
241 242

311 312
321 322
331 332
341 342

Conceptually displaying a 3D container in 2D is bad enough. Greater than 3 in a 2D environment is a nightmare.
Topic archived. No new replies allowed.
Pages: 12