2D-array member initialization

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
const int NumMarbles[] = {5, 8, 4};
const int NumColours = sizeof (NumMarbles) / sizeof NumMarbles[0];
const int NumMarblesAdded[][NumColours] = {{1,2,3}, {2,0,1}, {2,1,2}};
const int NumDraws = 5;

class ProbabilityTree {
public:
	ProbabilityTree (const int _numMarbles[], const int _numMarblesAdded[][NumColours], int _numDraws, int _numColours): 
		numMarbles (_numMarbles), numDraws (_numDraws), numColours (_numColours)
		/*, numMarblesAdded (_numMarblesAdded)*/ {
			numMarblesAdded = new int*[numColours];
			for (int i = 0; i < numColours; i++)
				for (int j = 0; j < numColours; j++)
				{
					numMarblesAdded[i] = new int[numColours];
					numMarblesAdded[i][j] = _numMarblesAdded[i][j];
				}
	}
private:
	const int numColours;
	const int *numMarbles;
	int **numMarblesAdded;
	const int numDraws;
};

int main () {
	ProbabilityTree tree (NumMarbles, NumMarblesAdded, NumDraws, NumColours);
	return 0;
}


The above compiles, but I don't like the way it is done. I can't declare int **numMarblesAdded to be const for one thing. The commented-out part is what I want to do, so then **numMarblesAdded can be declared const. What must I change to make that part compile?
Last edited on
Well, then that's a hole in the C++ language if there is no way to do this, right?
EDIT: Deleted my previousresponse, as I didn't read your code properly. I would have thought the commented-out line was legal, as the name of an array can be used as a pointer. I don't know what I'm missing there.

However, I'd recommend ditching arrays completetly, and using vectors from the standard library. They're much safer and more useful. For a start, they have assignment operators and copy constructors defined, so that you can copy them with a single initialisation like you're trying to do.

Once you learn how to use them, you won't look back.

Last edited on
Ok, using
const std::vector<std::vector<int>> numMarblesAdded;
instead then. Just wondering when the day will come when pointers to arrays will be superseded by vectors completely.
Last edited on
Just wondering when the day will come when pointers to arrays will be superseded by vectors completely.

About 5 years ago, by my reckoning.

OK, that's being glib. Obviously, there are some circumstances where you still need to use raw C-style arrays, e.g.

- when constrained to by 3rd-party/legacy API's
- when memory and/or speed efficiency is absolutely critical

And for learning purposes, I can understand wanting students to learn how to do it the old-fashioned way, as pointers, memory management and pointer arithmetic are still important fundamentals of C++ programming that people should learn IMHO.

But it's been years since I've worked anywhere where, outside of special circumstances, it would be considered acceptable to write new code with C-style arrays instead of some kind of container class, such as a std::vector.
1
2
const int foo[Y][X];
int **bar = foo; //error 

Can be used like is not the same as IS-A.

'bar' is a pointer variable. The variable takes as much space as one pointer (i.e. memory address) does require. The value in the variable should be a memory address of an allocated memory block that contains one (or more) pointer variables. You can do pointer math: bar[z] i.e. *(bar+z) to retrieve a pointer form location relative to the bar location. +1 on z means as many bytes as one pointer requires. You can then dereference that pointer (with pointer math) to retrieve an int from some memory location.

'foo' is an array. It represents a block of memory. It contains information that foo[z] means same as memory address of that start of the block plus z*X. That is a computed pointer that can be dereferenced, but not assigned to. It is not stored in memory location, like the pointer bar[z] is. +1 on z means as many bytes as X integers do require.

In principle both 'foo' and 'bar' know what "one pointer increment" means for them, but they are quite incompatible.

Besides, copy of an address is a "shallow copy", while copy of content is "deep copy". Both are desirable in different situations.


One more thing. This is definitely wrong:
1
2
3
4
5
6
7
8
9
int **foo = new int* [rows];
for ( size_t i = 0; i < rows; ++ i )
  {
    for ( size_t j = 0; j < cols; ++j )
      {
        foo[i] = new int[cols]; // Done rows*cols times
        foo[i][j] = bar[i][j];
      }
  }

Should be:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int **foo = new int* [rows];
for ( size_t i = 0; i < rows; ++ i )
  {
    foo[i] = new int[cols]; // Done rows times
    for ( size_t j = 0; j < cols; ++j )
      {
        foo[i][j] = bar[i][j];
      }
  }

for ( size_t i = 0; i < rows; ++ i )
  {
    delete [] foo[i];
  }
delete [] foo;

However, even closer to array:
1
2
3
4
5
6
7
8
9
10
int **foo = new int* [rows];
foo[0] = new int [rows*cols];
for ( size_t i = 1; i < rows; ++ i )
  {
    foo[i] = &foo[i-1][cols];
  }
...

delete [] foo[0];
delete [] foo;

Last edited on
Topic archived. No new replies allowed.