-1

So assume I have a matrix A where

unsigned int ** A = new unsigned int *[n];
  for(int j = 0; j<n; j++){
    A[j] = new unsigned int[m];
  }

I kinda struggle to understand why we would do it with pointers here and not just

unsigned int A = new unsigned int [n];
  for(int j = 0; j<n; j++){
    A[j] = new unsigned int[m];
  }

Also in both cases I can access values to A as A[0][0] - why do I not have to de-refence it in the first case i.e **A[0][0]=1?

CutePoison
  • 4,679
  • 5
  • 28
  • 63
  • 3
    Your code won't work when `sizeof(unsigned int)` is different to `sizeof(unsigned int *)`. – Dai Nov 29 '19 at 00:56
  • 2
    Does this answer your question? [How do I use arrays in C++?](https://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c) – Ken Y-N Nov 29 '19 at 00:59
  • In particular, [this answer deals with 2D arrays](https://stackoverflow.com/a/4810676/1270789). – Ken Y-N Nov 29 '19 at 01:00
  • 8
    *I kinda struggle to understand why we would do it with pointers here and not just* -- Because C++ is not Python, Java, or whatever other language you've been using. The `new` keyword always returns a pointer. – PaulMcKenzie Nov 29 '19 at 01:02
  • So you cannot create a 2D array in C++ without using pointers? – CutePoison Nov 29 '19 at 01:04
  • 1
    Because the 2nd example is not valid C++. Furthermore, with the first example, the reason you can't compile "`**A[0][0]=1`" is because that's not how C++ works. In C++, the subscript operator already dereferences the pointer. – Sam Varshavchik Nov 29 '19 at 01:04
  • 1
    Of course you can create a 2D array in C++ without pointers: `unsigned int A[10][10]`. There's your 2D array. You can't create 2D arrays, or any arrays of any kinds, of some size that's determined at runtime, unless you use pointers. – Sam Varshavchik Nov 29 '19 at 01:05
  • So `A[0][0]` does the dereference? – CutePoison Nov 29 '19 at 01:05
  • 4
    Yes, see your C++ book for more details. This should be explained in every C++ book. Unfortunately, stackoverflow.com is not a replacement for a C++ book, so if you want to learn more about this, the most complicated general purpose programming language in use today, you'll need to start reading that book. That's the only way to go that way. – Sam Varshavchik Nov 29 '19 at 01:05
  • 1
    I will dig deeper into the book then. – CutePoison Nov 29 '19 at 01:07
  • 1
    `int A` is a scalar. `int *A` points to a vector. `int **A` points to a vector of vectors. – user207421 Nov 29 '19 at 01:14
  • wouldnt `int *A` just be a pointer to an int? – CutePoison Nov 29 '19 at 01:15
  • In general (not in this particular case) – CutePoison Nov 29 '19 at 01:20
  • `int *A` could point to a single `int` or point to an array of `int`. It's the same type. – Blastfurnace Nov 29 '19 at 01:46
  • 3
    @user207421 Wrong. `int *A` does not point to a vector - it is a variable that contains the address of an `int`. Similarly, `int **A` does not point to a vector of vectors - it is a variable that contains the address of a pointer, which in turn can contain the address of an `int`. – Peter Nov 29 '19 at 01:47
  • 1
    @Peter Not wrong. They can be both. *In this case* the pointers are both pointers to vectors. – user207421 Nov 29 '19 at 03:03
  • The discussion of @user207421 and @Peter shows IMHO this: Arrays "stored" in pointers are a bad idea in general. Every info except the element type and the start address gets lost. It might be necessary in C but C++ just inherited them from C and evolved with much better alternatives, e.g. references to arrays (`int (&arr)[10][20]`) or `std` containers or custom classes which just behave like arrays (due to overloading of `operator[]`) or what else I just forgot to mention. – Scheff's Cat Nov 29 '19 at 07:43
  • @user207421 - the pointers are given values to dynamically allocated memory and then used AS IF they are vectors. That doesn't make them vectors. – Peter Nov 29 '19 at 09:20

1 Answers1

0

For the first example, as to why you do not have to do any dereferencing, is that I am guessing the compiler is doing the heavy lifting. What is probably occurring is that A[i][j] will increment a copy of the value of A as a new address value by j * sizeof(unsigned int *), then it will be assigned the address that is stored at A[j], as demonstrated by the fact that if you dereference *A[i], you will get the first value in the ith array. It will then increment the value of our address pointer by j * sizeof(unsigned int) to get to the number you are looking for.

The second example does not compile for me. You can also just do unsigned int A[n][m];

  unsigned int n = 10;
  unsigned int m = 15;
  double ** A = new double * [n];
  for(int i = 0; i < n; ++i) {
    A[i] = new double[m]{1, 2, 3, 4};
  }

  std::cout << A << "\t" << *A << std::endl;
  for(int j = 0; j < n; ++j) {
    std::cout << A[j] << "\t" << *A[j] << "\t" << A[j][0] << std::endl;
  }
  for(int j = 0; j < n; ++j) {
    delete(A[j]);
  }
  delete(A);

I hope this helps!

Max Wright
  • 41
  • 3