How make a dynamic array using void** and void*? - c++

I want to make a dynamic memory array function where in the arguments I can put in any type I want, the count, and the item I want. I've been googling and looking at YT videos, but none of them explain how to do just THAT, and when the item I want is a pointer. For example, I would have this:
struct Entity
{
int health;
int level;
int experience;
char* name;
}
Entity** entitylist = NULL;
int entitycount = 0;
Entity* CreateEntity(/*args for creating an entity*/)
{
Entity* newentity = malloc(sizeof(Entity));
// All of the entity creation stuff and at the end...
AddItemToList(&Entity, &newentity, &entitycount);
}
I know in the function I want to create I would need to pass in references to the specific list, but from that I'm pretty much clueless. I've tried to use malloc and realloc but either crashes the program or does nothing. And would new and delete work for this type of stuff?
And how would removing something like this work? I haven't seen anything on the internet yet about removing an item from a list, only adding them.
Thanks!

Using a double pointer for a data type such as int** with give you a dynamic 2D array, or a dynamic array of pointer objects, depending on your implementation, and a single int* is just a normal dynamic array. To full instantiate and allocate the memory for these, here's how you do it:
1D Dynamic array:
int* arr;
arr = new int[SIZE];
2D Dynamic Array:
int** arr;
arr = new int*[SIZE]; //<- stop here for 1D array of pointer objects
for (int i = 0; i < SIZE; i++)
arr[i] = new int[SIZE2];

Related

Does this make an array of pointers?

So I'm trying to make a dynamically allocated array. To do that I'm trying to make an array of pointers. I used typedef to define the pointer type and tried to create the array of pointers using this code.
emprec * arrptr = new emprec[size];
my question is, is this the correct way to create an array of pointers? If not, what would be a better way of doing so.
emprec is defined in the program as seen below
struct emprec
{
int id;
float salary;
};
typedef emprec * emprecptr;
typedef emprec arr[MAXDBSIZE];
(I am a student and I'm trying to learn more about dynamic allocation)
After the kind help of you guys on here, it was made clear that I originally made an array of emprec which would be an array of structs. I didn't want that. Changing the code to
emprecptr* DBarray = new emprecptr[dbsize];
now gives me an array of pointers.
Given
struct emprec
{
int id;
float salary;
};
then, no
emprec * arrptr = new emprec[size];
is not an array of pointers, but an array of emprec's. But since you also had typedef emprec * emprecptr;, then
emprecptr * arrptr = new emprecptr[size];
would be an array of pointers (to emprec). Without the typedef you would have to write it as:
emprec* * arrptr = new emprec*[size];
But as you can see, the typedef simplifies the understanding of the code and possibly, makes it easier to read.
First point is not to confuse an array of pointers with a pointer to an array. You said the first, so I'm going to take you at your word. But what follows is misleading if you really meant the second.
In general to create a dynamic array of T you write
T* arr = new T[size];
Since you want an array of pointers T must be a pointer. For instance here is how to create an array of integer pointers.
int** arr = new int*[size];
Similarly an array of pointers to emprec would be
emprec** arr = new emprec*[size];
This can be simplifed using the typedef in your question to
emprecptr* arr = new emprecptr[size];

C++ Pointer of Array of Ints Initialization

I want to have an array accessible by all functions of a class.
I put the array as private variable in the header file.
private:
int* arrayName;
In the .cpp file where I implement the class, the constructor takes in an int value (size) and creates the array. The goal is to fill it up
ClassName::ClassName(int numElements){
arrayName = new int[numElements]; //make arrays the size of numElements
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
}
I feel like this is quite inefficient. I know you can do int array[5] = {0}; but how do you do it when you don't initially know the size.
If you want to zero-initialize a newed array, just do value-initialize it. This has the effect of zero-initializing its elements:
arrayName = new int[numElements]();
// ^^
But you really want to be using an std::vector<int>.
private:
std::vector<int> vname;
and
ClassName::ClassName(int numElements) : vname(numElements) {}
This way you don't have to worry about deleting an array and implementing copy constructors and assignment operators.
You can use the memset function:
memset(arrayName,0,sizeof(int)*numElements);
This void * memset ( void * ptr, int value, size_t num ); function sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
To use it you must include the string.h header file.
For more information: http://www.cplusplus.com/reference/cstring/memset/
What you want to do is progressively expand the array on demand.
arrayName = new int[numElements];
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
The above code (what you gave) will give you an array of size numElements, and THEN the for loop will fill it. This is allocated now, and can't, as I understand it, be simply or easily resized (memset will overwrite previously held values in the array).
You could copy the whole array over every time you want to resize it:
int * oldarr = new int[OldSize];
//fill your old array
int * newarr = new int[NewSize];
for(int i = 0; i<OldSize; i++)
newarr[i] = oldarr[i];
Other than that, you could make the array much larger, or you could use various STLs, such as std::vector. Vector can be increased with a simple push_back function, and allows [] operator access (like arr[5] and whatnot).
Hope this helps!

c++:defining function which can work as growable array

i want growable array for my project. I am trying to define a function that can give me replaced array with new size.I want some idea how can i do this.
int growarray[10];
int length =20;
//grow increase size of growarray to 20
void grow(int length){
}
std::vector would be the ideal way to do this, if you really want to code your own dynamic array you'll need to declare your array on the heap and do something like this...
int* growarray = new int[10];
and then to "expand" it...
int* temp = new int[20];
memcpy(temp, growarray, 10);
delete[] growarray;
growarray = temp;
when using this sort of technique you generally expand the array by a constant factor(usually 2 but some libraries use all sorts of different factors)

initialize an int[][] with new()

I am a c++ newbie. While learning I came across this.
if I have a pointer like this
int (*a)[2][3]
cdecl.org describe this as declare a as pointer to array 2 of array 3 of int:
When I try
int x[2][3];
a = &x;
this works.
My question is how I can initialize a when using with new() say something like
a = new int [] [];
I tried some combinations but doesn't get it quite right.
Any help will be appreciated.
You will have to do it in two steps - first allocate an array of pointers to pointers(dynamically allocated arrays) and then, allocate each of them in turn. Overall I believe a better option is simply to use std::vector - that is the preferred C++ way of doing this kind of things.
Still here is an example on how to achieve what you want:
int a**;
a = new int*[2];
for (int i =0; i< 2;++i){
a[i] = new int[3]
}
... use them ...
// Don't forget to free the memory!
for (int i = 0; i< 2; ++i) {
delete [] a[i];
}
delete [] a;
EDIT: and as requested by Default - the vector version:
std::vector<std::vector<int> > a(2, std::vector<int>(3,0));
// Use a and C++ will take care to free the memory.
It's probably not the answer you're looking for, but what you
need is a new expression whose return type is (*)[2][3] This
is fairly simple to do; that's the return type of new int
[n][2][3], for example. Do this, and a will point to the
first element of an array of [2] of array of [3] int. A three
dimensional array, in sum.
The problem is that new doesn't return a pointer to the top
level array type; it returns a pointer to the first element of
the array. So if you do new int[2][3], the expression
allocates an array of 2 array of 3 int, but it returns
a pointer to an array of 3 int (int (*a)[3]), because in C++,
arrays are broken (for reasons of C compatibility). And there's
no way of forcing it to do otherwise. So if you want it to
return a pointer to a two dimensional array, you have to
allocate a three dimensional array. (The first dimension can be
1, so new [1][2][3] would do the trick, and effectively only
allocate a single [2][3].)
A better solution might be to wrap the array in a struct:
struct Array
{
int data[2][3];
};
You can then use new Array, and everything works as expected.
Except that the syntax needed to access the array will be
different.

allocation of a pointers to fixed size arrays

I have 2 doubts regarding basics of pointers usage.
With the following code
int (*p_b)[10];
p_b = new int[3][10];
// ..do my stuff
delete [] p_b
p_b is pointing to an array of 3 elements, each having fixed-size length of 10 int.
Q1:
How to declare p_b if I want that each element be a pointer to a fixed array size?
Basically I want the following
p_b[0] = pointer to a fixed-array size of 10
p_b[1] = pointer to a fixed-array size of 10
// ... and so on
I was thinking to int (** p_b)[10] but then I don't know how to use new to allocate it? I would like to avoid falling back to more general int** p_b
Q2:
Is per my original code sample above, how to call new so that p_b points to a unique fixed-size array of 10 int other than calling p_b = new int[1][10] ? To free memory I have to call delete[] while I cannot find an expression where I can call only simply delete.
p_b is pointing to an array of 3 elements, each having fixed-size length of 10 int.
How to declare p_b if I want that each element be a pointer to a fixed array size?
Does your first sentence not completely cover that question?
Is per my original code sample above, how to call new so that p_b points to a unique fixed-size array of 10 int other than calling p_b = new int[1][10]? To free memory I have to call delete[] while I cannot find an expression where I can call only simply delete.
I completely do not understand why this is a problem, but you could do it by wrapping your array inside another type... say std::array, boost::array or std::vector.
First of all, if your new expression has square brackets (new somtype[somesize]), your delete has to have square brackets as well (delete [] your_pointer).
Second, right now you've defined p_b to be a single pointer to some data. If what you really want is an array of pointers, then you need to define it as an array. Since you apparently want three independent arrays, you'll have to allocate each of them separately. It's probably easiest if you start with a typedef:
typedef int *p_int;
p_int p_b[3];
Then you'll allocate your three arrays:
for (int i=0; i<3; i++)
p_b[i] = new int[10];
To delete those, you'll need to delete each one separately:
for (int i=0; i<3; i++)
delete [] p_b[i];
I definitely agree with #Tomalak that you should almost never mess with things like this yourself though. It's not clear what you really want to accomplish, but it's still pretty easy to guess that chances are quite good that a standard container is likely to be a simpler, cleaner way to do it anyway.
Here's an example of how to implement Q1:
int main()
{
typedef int foo[10];
foo* f = new foo[3];
f[0][5] = 5;
f[2][7] = 10;
delete [] f;
}
As for Q2, the only way to delete memory allocated with new[] is with delete[]. If you personally don't want to write delete [], you can use a vector or another STL container. Really, unless this is some hardcore uber-optimisation, you should be using vectors anyway. Never manage memory manually unless you are absolutely forced to.
To use a raw pointer to manage a 2-d array you must first create a pointer to a pointer to array element type that will point to each row of the array. Next, each row pointer must be assigned to the actual array elements for that row.
int main()
{
int **p;
// declare an array of 3 pointers
p = new int*[3];
// declare an array of 10 ints pointed to by each pointer
for( int i = 0; i < 3; ++i ) {
p[i] = new int[10];
}
// use array as p[i][j]
// delete each array of ints
for( int i = 0; i < 3; ++i ) {
delete[] p[i];
}
// delete array of pointers
delete[] p;
}
A far easier solution is to use std::array. If your compiler does not provide that class you can use std::vector also.
std::array<std::array<int,10>,3> myArr;
myArr[0][0] = 1;
For Q1, I think you want
int (*p[3])[10];
Try cdecl when you're unsure.
Your other question seems to be well answered by other answers.
regards,
Yati Sagade
Actually, nobody posted an answer to your exact question, yet.
Instead of
int (*p_arr)[10] = new int[3][10];
// use, then don't forget to delete[]
delete[] p_arr;
I suggest using
std::vector<std::array<int, 10>> vec_of_arr(3);
or if you don't need to move it around and don't need runtime length:
std::array<std::array<int, 10>, 3> arr_of_arr;
Q1
How to declare p_b if I want that each element be a pointer to a fixed array size?
int(**pp_arr)[10] = new std::add_pointer_t<int[10]>[3];
for (int i = 0; i < 3; ++i)
pp_arr[i] = new int[1][10];
// use, then don't forget to delete[]
for (int i = 0; i < 3; ++i)
delete[] pp_arr[i];
delete[] pp_arr;
The modern variant of that code is
std::vector<std::unique_ptr<std::array<int, 10>>> vec_of_p_arr(3);
for (auto& p_arr : vec_of_p_arr)
p_arr = std::make_unique<std::array<int, 10>>();
or if you don't need to move it around and don't need runtime length:
std::array<std::unique_ptr<std::array<int, 10>>, 3> arr_of_p_arr;
for (auto& p_arr : arr_of_p_arr)
p_arr = std::make_unique<std::array<int, 10>>();
Q2
Is per my original code sample above, how to call new so that p_b points to a unique fixed-size array of 10 int other than calling p_b = new int[1][10]?
Not without wrapping the array into another type.
std::array<int, 10>* p_arr = new std::array<int, 10>;
// use, then don't forget to delete
delete p_arr;
You can replace std::array<int, 10> with your favourite array-wrapping type, but you cannot replace it with a fixed-size array alias. The modern variant of that code is:
auto p_arr = std::make_unique<std::array<int, 10>>();