I am a Fortran user and do not know C++ well enough. I need to make some additions into an existing C++ code. I need to create a 2d matrix (say A) of type double whose size (say
The formal C++ way of doing it would be this:
std::vector> a;
This creates container which contains a zero size set of sub-containers. C++11/C++13 provide std::array
for fixed-sized containers, but you specified runtime sizing.
We now have to impart our dimensions on this and, unfortunately. Lets assign the top-level:
a.resize(10);
(you can also push
or insert
elements)
What we now have is a vector
of 10 vectors. Unfortunately, they are all independent, so you would need to:
for (size_t i = 0; i < a.size(); ++i) {
a[i].resize(10);
}
We now have a 10x10. We can also use vector
s constructor:
std::vector> a(xSize, std::vector(ySize)); // assuming you want a[x][y]
Note that vectors are fully dynamic, so we can resize elements as we need:
a[1].push_back(10); // push value '10' onto a[1], creating an 11th element in a[1]
a[2].erase(2); // remove element 2 from a[2], reducing a[2]s size to 9
To get the size of a particular slot:
a.size(); // returns 10
a[1].size(); // returns 11 after the above
a[2].size(); // returns 9 after teh above.
Unfortunately C++ doesn't provide a strong, first-class way to allocate an array that retains size information. But you can always create a simple C-style array on the stack:
int a[10][10];
std::cout << "sizeof a is " << sizeof(a) <<'\n';
But using an allocator, that is placing the data onto the heap, requires /you/ to track size.
int* pointer = new int[10];
At this point, "pointer" is a numeric value, zero to indicate not enough memory was available or the location in memory where the first of your 10 consecutive integer storage spaces are located.
The use of the pointer decorator syntax tells the compiler that this integer value will be used as a pointer to store addresses and so allow pointer operations via the variable.
The important thing here is that all we have is an address, and the original C standard didn't specify how the memory allocator would track size information, and so there is no way to retrieve the size information. (OK, technically there is, but it requires using compiler/os/implementation specific information that is subject to frequent change)
These integers must be treated as a single object when interfacing with the memory allocation system -- you can't, for example:
delete pointer + 5;
to delete the 5th integer. They are a single allocation unit
; this notion allows the system to track blocks rather than individual elements.
To delete an array, the C++ syntax is
delete[] pointer;
To allocate a 2-dimensional array, you will need to either:
Flatten the array and handle sizing/offsets yourself:
static const size_t x = 10, y = 10;
int* pointer = new int[x * y];
pointer[0] = 0; // position 0, the 1st element.
pointer[x * 1] = 0; // pointer[1][0]
or you could use
int access_2d_array_element(int* pointer, const size_t xSize, const size_t ySize, size_t x, size_t y)
{
assert(x < xSize && y < ySize);
return pointer[y * xSize + x];
}
That's kind of a pain, so you would probably be steered towards encapsulation:
class Array2D
{
int* m_pointer;
const size_t m_xSize, m_ySize;
public:
Array2D(size_t xSize, size_t ySize)
: m_pointer(new int[xSize * ySize])
, m_xSize(xSize)
, m_ySize(ySize)
{}
int& at(size_t x, size_t y)
{
assert(x < m_xSize && y < m_ySize);
return m_pointer[y * m_xSize + x];
}
// total number of elements.
size_t arrsizeof() const
{
return m_xSize * m_ySize;
}
// total size of all data elements.
size_t sizeof() const
{
// this sizeof syntax makes the code more generic.
return arrsizeof() * sizeof(*m_pointer);
}
~Array2D()
{
delete[] m_pointer;
}
};
Array2D a(10, 10);
a.at(1, 3) = 13;
int x = a.at(1, 3);
Or,
For each Nth dimension (N < dimensions) allocate an array of pointers-to-pointers, only allocating actual ints for the final dimension.
const size_t xSize = 10, ySize = 10;
int* pointer = new int*(x); // the first level of indirection.
for (size_t i = 0; i < x; ++i) {
pointer[i] = new int(y);
}
pointer[0][0] = 0;
for (size_t i = 0; i < x; ++i) {
delete[] pointer[i];
}
delete[] pointer;
This last is more-or-less doing the same work, it just creates more memory fragmentation than the former.
-----------EDIT-----------
To answer the question "why do I not have 10" you're probably compiling in 64-bit mode, which means that "x" is an array of 10 pointers-to-int, and because you're in 64-bit mode, pointers are 64-bits long, while ints are 32 bits.