How To Implement Linear Arrays in C++?

Apr 9, 2018 at 8:31am
Hello Professionals,

Good day. I just realized that it's better to implement arrays in C++ such as shown below:

index = [(i*height*depth) + (j*depth) + k]

However, I am still new to this implementation, and I wanted to ask your advice how will I implement this?

For example, if I have a set of values:

1 2 3
4 5 6
7 8 9

Wherein:
1 is at [0][0] index
2 is at [0][1] index
3 is at [0][2] index
4 is at [1][0] index
5 is at [1][1] index
6 is at [1][2] index
7 is at [2][0] index
8 is at [2][1] index
9 is at [2][2] index

How can I effectively utilize the [(i*height*depth) + (j*depth) + k] to completely access the values above?
Apr 9, 2018 at 9:18am
Using a multidimensional array:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

int main()
{
	const int height = 3;
	const int width  = 3;
	
	int m[height][width] = 
	{
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 9}
	};
	
	for (int y = 0; y < height; ++y)
	{
		for (int x = 0; x < width; ++x)
		{
			std::cout << m[y][x] << ' '; 
		}
		std::cout << '\n';
	}
}

Using a linear array:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

int main()
{
	const int height = 3;
	const int width  = 3;
	
	int m[height * width] = 
	{
		1, 2, 3,
		4, 5, 6,
		7, 8, 9
	};
	
	for (int y = 0; y < height; ++y)
	{
		for (int x = 0; x < width; ++x)
		{
			std::cout << m[y * width + x] << ' '; 
		}
		std::cout << '\n';
	}
}
Apr 9, 2018 at 2:09pm
I highly recommend a thin class that has the dimensions and wraps this in an inline function that does the math for you so you can just have
thing.set(row,col, value);
I don't know if there is a way to overload an operator to make this cleaner. Probably.

note that for arrays, it does not matter:

x[10][20] IS a solid block of bytes, you can collapse it to 1d with pointer magic (type * oned = & x[0][0]).

the issue is dynamic arrays and vectors that get a block for each row.

type ** ugly;
ugly = new type*[size]; //one block of memory.
for(i=... size)
ugly[i] = new type[size2];//multiple blocks of memory in random places in ram.

this is fragmented and causes page faults and problems and can't be directly iterated to touch all items and is a performance hit for large data.

Apr 9, 2018 at 9:21pm
thing.set(row,col, value);
I don't know if there is a way to overload an operator to make this cleaner. Probably.

You can do it with a helper class. think.operator[] returns an instance of the helper. Helper.operator[] returns the data that you really want. This lets you say thing[row][col]. Here's a simplified example.
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
#include <iostream>

class TwoDArray {
public:
    TwoDArray(size_t r, size_t c) :
	rows(r), cols(c)
    {
	data = new int[rows*cols]{};
    }
    ~ TwoDArray() {
	delete[] data;
    }
    class TwoDIdx {
    public:
	TwoDIdx(TwoDArray &arr, size_t r) :
	    array(arr), row(r) {}
	TwoDArray &array;
	size_t row;
	int &operator [] (size_t col) {
	    return array.data[col*row];
	}
    };
    TwoDIdx operator[](size_t idx) {
	return TwoDIdx(*this, idx);
    }

private:
    size_t rows, cols;
    int *data;
};


    
int
main()
{
    TwoDArray arr(10,15);
    arr[3][4] = 7;
    
    for (size_t c=0; c<15; ++c) {
	std::cout << arr[3][c] << ' ';
    }
    std::cout << '\n';
    return 0;
}
Apr 10, 2018 at 2:03pm
Nice example, TY. I should have known that, but was mentally hung up thinking about the syntax and not working the actual problem.


Apr 23, 2018 at 1:51am
Thank you very much guys for sharing your thoughts. God bless you all! :)
Topic archived. No new replies allowed.