2

I know how to create an 1d array (like a[10]) through an allocator. For instance, here is an abstract from cppreference:

#include <memory>
#include <iostream>
#include <string>
int main()
{
    std::allocator<int> a1; // default allocator for ints
    int* a = a1.allocate(10); // space for 10 ints

    a[9] = 7;

    std::cout << a[9] << '\n';
   // the remainder was omitted .....
    return 0;
}

I do not, however, know how to create a 2D array, like int a[10][10]. Can someone help me with that, please?

slawekwin
  • 6,270
  • 1
  • 44
  • 57
Savner_Dig
  • 21
  • 1
  • 8

3 Answers3

3

int[10][10] is an array type of 10 elements. The element type is int[10]. So the equivalent of that allocation would be:

std::allocator<int[10]> a2;
int (*a)[10] = a2.allocate(10);

You could simplify the code with a type alias, e.g:

using A = int[10];
std::allocator<A> a2;
A *a = a2.allocate(10);

Note that the cppreference example incorrectly went on to write a[9] = 7;. The allocate function allocates storage but does not create objects in the storage. (The standard explicitly says this, C++14 table 28). And it is undefined behaviour to use the assignment operator with a left-hand operand that does not designate an object. You would need to subsequently use placement-new to create objects, before using the assignment operator. The example has now been fixed to use construct instead of allocate.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Lifetime of an int begins when storage is allocated: [basic.life]p1.1 – Cubbi Apr 24 '17 at 13:23
  • @Cubbi That section means that *if code that creates an int object is executed*, then the point of beginning of that int object's lifetime is the point when the storage was allocated. Just allocating storage does not create any particular object. If you malloc 4 bytes does that create an int or a float, in your picture? (I have seen someone argue that it creates one each of all possible 4-byte objects superimposed!) Anyway, I don't wish to have this argument in comments , I would refer you to [this answer](http://stackoverflow.com/a/40874245/1505939) for Standard ref and discussion – M.M Apr 25 '17 at 01:23
  • oh, that discussion. I think gratuitous incompatibility with C is a defect, but I agree it's good idea to call allocator::construct there regardless.. cppreference updated, thanks. – Cubbi Apr 25 '17 at 02:24
  • @M.M i am really appreciate your comment and warning to which you just point a example in cppreference, and may you completely write the code(involving properly create a object by using int (*a)[10]=a2.allocate(10)),thanks hero! – Savner_Dig Apr 25 '17 at 14:12
0

You can instead allocate 100 and access using y*10 + x. This is how the compiler generates the index for a[10][10]

int* a = allocate(100);
a[5*10 + 2] = 9; //a[5][2]
Danny Birch
  • 603
  • 4
  • 16
0

If the size of the array is fixed then you can simply write

int a[10][10]; 

and allocation will be on the stack for local variables or in the data or bss segment for global variables (depending on whether you initialize the array members or not).

If you want to allocate the size of the array dynamically, I would suggest to use std::vector instead of an array. Using the std::allocator you would write

std::vector<std::vector<int>> a(10, std::vector<int>(10)); 

std::vector also can take a second template parameter to define an allocator different from std::allocator. Note that the memory is not allocated continuously.

A possibility for dynamic sized 2D arrays with continuous array sizes is described here.

Gert Wollny
  • 529
  • 2
  • 8