Dynamically Changing the Size of the Pointer in C++ - c++

I have the following structure
typedef struct DeviceInfo
{
char[30] name;
char[30] serial Number;
}DeviceInfo;
I am doing this
DeviceInfo* m_DeviceInfo = new DeviceInfo[4];
// Populate m_DeviceInfo
Then I wanted to re size m_DeviceInfo to 6 and want to preserve the
Previous 4 Value as well.
How to do it in c++ ?

You can't do that with regular arrays. I suggest you to use vector which is able to grow as you add more elements to it (so you don't even have to specify initial size).

The good C++ way is to use an appropriate container for that. Apparently, you should use the std::vector container, e.g:
std::vector<DeviceInfo> m_DeviceInfo;
m_DeviceInfo.resize(4);
This requires some constraints on your DeviceInfo. In particular, it should have a constructor without arguments, and copy constructors...
And your question is badly phrased. You certainly don't change sizeof(DeviceInfo*) which is probably 4 bytes on a 32 bits machine, and 8 bytes on a 64 bits one.

m_DeviceInfo points to an array of DeviceInfo of 4 elements. There is no resizing with arrays. Instead you should delete and create it with 6 elements.
DeviceInfo * m_DeviceInfo2 = new DeviceInfo[6];
memcopy( m_DeviceInfo,m_DeviceInfo2, 4 );
delete[] m_DeviceInfo;
But you should use a vector.
std::vector<DeviceInfo> m_DeviceInfo;
// or
std::vector<std::shared_ptr<DeviceInfo>> m_DeviceInfo;
To resize it
m_DeviceInfo.resize(m_DeviceInfo.size()+ 2);

You have two options in your problem and it depends if you want to use STL or not.
typedef struct DeviceInfo
{
char[30] name;
char[30] serial Number;
} DeviceInfo;
With STL:
//requires vector.h
vector<DeviceInfo> m_deviceInfo;
DeviceInfo dummy;
dummy.name = "dummyName";
dummy.serialNumber = "1234";
m_deviceInfo.insert(m_deviceInfo.begin(), dummy);
//add as many DeviceInfo instance you need the same way
or without STL:
//implement this
DeviceInfo* reallocArray(DeviceInfo* arr, int curItemNum, int newItemNumber)
{
DeviceInfo* buf = new DeviceInfo[newItemNumber];
for(int i = 0; i < curItemNum; i++)
buf[i] = arr[i];
for(int i = curItemNum; i < newItemNumber; i++)
buf[i] = null;
}
//and in your main code
DeviceInfo m_DeviceInfo = new DeviceInfo[4];
m_DeviceInfo = reallocArray( m_DeviceInfo, 4, 6 );

1) Make a new array of size that fits, and copy all elements of the old array to the new one.
2) Use the std::vector (my recommendation).

The best possible solution is using vector in your program.
Refer this site http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html#VECTOR
This site will help you to solve your problem.
Here you can push the data.No need to bother about the size of structure.

Your syntax is wrong:
DeviceInfo m_DeviceInfo = new DeviceInfo[4];
should be:
DeviceInfo* m_DeviceInfo = new DeviceInfo[4];
A better alternative would be the use of std::vector.
std::vector<DeviceInfo> vec;
//populate:
DeviceInfo inf;
vec.push_back(inf);
vec.push_back(inf);
//....

well there are several ways to do this, but
you should use the realloc function in c++. it will reallocate contiguous memory and also copies the value of previous memory into the new ones. for example:
temp_DevInfo = (DeviceInfo*) realloc (m_DeviceInfo, (2) * sizeof(struct DeviceInfo));
free(m_DeviceInfo);
m_deviceInfo = temp_DevInfo;
you do 2 * sizeof(DeviceInfo) because you want to add 2 more, plus the previous 4 is 6.
then you should free/delete the previous object.
and finally set old pointer to point to the new object you just allocated.
that should be the gist of it
look at the documentation of realloc.

Related

Setting raw data of array with elements of dynamic size (vector to/from void*)

I need to store and restore a vector with elements of different size and want to adjust my solution to get this working. The goal is to get a size of the data in bytes + get a void pointer to the beginning of the data.
I use a template class in my code and combine solution 1 and 2 in it, but for the sake of simplicity I split the code up in this question.
1) Solution for a vector of elements where all elements have the same size:
1.1) Save a vector as raw data - with fixed size elements, e.g. int:
std::vector<int> data;
Sint32 size = sizeof(int) * vec.size();
void* tdata = static_cast<void*>(&vec[0]);
// tdata points to the raw data => I can work with this now and save it to my memory structure (tdata + size is saved there)
1.2) Restore a vector from raw data - with fixed size elements, e.g. int:
std::vector<int> vec;
size_t size = ...; // received from my memory structure
void* tdata = ...; // received from my memory structure
int count = size / sizeof(int);
vec.resize(count);
memcpy(&vec[0], tdata, size);
// vec contains count elements of type int now
2) Solution for a vector of elements where all elements have dynamic sizes:
I simply define two helper interfaces/classes to get the size of all elements inside the vector:
class ObjectWithSize
{
public:
// eg. for an int + char*: sizeof(int) + strlen(text) + 1
virtual int getRawSize() = 0;
};
class RawDataWithCount
{
public:
int count;
void* data;
};
2.1) Save a vector of dynamic elements:
Sint32 datasize = 0;
for (int i = 0; i < vec.size(); i++)
datasize += vec.at(i).getRawSize();
RawDataWithCount data = RawDataWithCount();
data.count = vec.size();
data.data = static_cast<void*>(&vec[0]);
void* tdata = static_cast<void*>(&data);
// tdata points to the raw data => I can work with this now and save it to my memory structure (tdata + datasize is saved there)
2.2) Restore a vector of dynamic elements
std::vector<T> vec;
size_t size = ...; // received from my memory structure
void* tdata = ...; // received from my memory structure
RawDataWithCount* data = reinterpret_cast<RawDataWithCount*>(tdata);
int count = data->count;
vec.resize(count);
memcpy(&vec[0], data->data, size);
Information
Solution 1 is used for a long time already and works quite good, solution 2 will be an extension of it for the future. I think, 2.1 is save to use, but when it comes to 2.2 I'm not sure anymore, so here comes the question. Tests show that solution 2 seems to work, but I want to know if it is save.
Question
Is it save to do following in 2.2
vec.resize(count);
memcpy(&vec[0], data->data, size);
if the elements of vec do not all have the same size? I assume not, but I'm unsure here. If this is not save, maybe someone has a better suggestion? (I know I can manually solve this by simple creating a raw data in 2.1 with number of elements followed by a list of size/element, then parsing back elements 1 by 1 in 2.2 and fill up the vector with this data, but maybe (like in case 1)
there is a more simple solution with the help of a vector?)

Failed to allocate an array of pointers to a struct

I'm trying to allocate an array of pointers to a struct but there's something wrong with my code.
This is my struct:
struct Brick {
GameObject2D* handle_;
};
Brick** bricks_;
And this is how i'm trying to allocate memory for it:
int bricks_amount_ = 10;
bricks_ = (Brick**)malloc(sizeof(Brick*) * bricks_amount_);
The program crash. I've make a devenv on it to debug where's the problem and it crash on this line:
for (unsigned short int i = 0; i < bricks_amount_; i++){
bricks_[i]->handle_ = new GameObject2D(); <---------- CRASH!
}
Any suggestions?
PS: Sorry for my english :P
=========================================================================
[SOLUTION]
Finally i've decided to use std::vector instead raw pointers:
bricks_.resize(bricks_amount_);
but i've tried to make the malloc different way and it works too:
bricks_ = (struct Brick*)malloc(sizeof(struct Brick) * bricks_amount_);
or this:
bricks_ = new Brick[bricks_amount_];
Thank you to the people who wants to help!
It's C++:
don't use malloc, use new
don't use plain arrays, use std::vector or std::array
don't use raw pointers, use std::unique_ptr
Do not use
Bricks ** //will be a 2 dimensional array
Use instead
Bricks * //will be a 1 dimensioanal array
If you want a single dimensional array
Then do
`Bricks * bricks_ = (Bricks *)malloc(sizeof(Brick) * bricks_amount_ );
`
Then you can safely do without a crash
for (unsigned short int i = 0; i < bricks_amount_; i++){
bricks_[i]->handle_ = new GameObject2D(); <---------- There will not be CRASH!
}

Memory allocation with unknown number of elements

Since the number of elements is determined by some conditions, I wrote a program like this;
int i = 0;
int *layer;
while (i != 12){
layer = new int;
layer[i] = i;
cout << layer[i] << endl;
i++;
}
delete[] layer;
return 0;
I get the result;
0
1
2
3
4
5
6
And then program crashes. What is the reason of this and how should I modify the program in order to allocate memory for unknown number of elements?
Thanks in advance!
You have undefined behaviour. You allocate space for a single int, then you treat it as an array.
layer = new int; // single int
layer[i] = i; // wat??
Then you leak the memory, then you call delete[] on the last newed int. Since it isn't clear what you want to do with your code, I can only offer some suggestions:
Consider using std::vector<int> as a dynamic array. It will save you a lot of trouble.
If you must allocate an array with new (you probably don't), you need new int[n] where n is the number of elements.
Call delete [] for every new[] and delete for every new.

Is it possible to create an array on the heap at run-time, and then allocate more space whenever needed?

Lets say I do
char *a;
a = new char[4];
Now, is it possible to extend the size of the array further?
Say I want to keep any values I put inside a[0] to a[3] but now I want more space for a[4] and a[5] etc. Is that possible in C++?
At first I felt like maybe I could just make:
char* a[10];
a[0] = new char[size];
Whenever more space is needed I can go to a[1] and allocate more space. This is the only alternative I can think of at the moment.
Unfortunately it's not possible in C++. You have to allocate a new area and copy the old into the new.
However, C++ have other facilities, like std::vector, that alleviates the need to manually handle these things.
Instead of char* a , you can use char** a;
i.e.
char** a = new char*[4];
for(int i=0; i<4; i++)
(*a)[i] = new char(i); /* feed values to array */
/* now you need a[4]? no problem */
char tmp = (*a)[3];
a[3] = new char[2];
a[3][0] = tmp;
a[3][1] = xyz; /* this is you a[4] */
Though this is a work around, I would suggest to used vector.

Reallocating 2D arrays on C++

lets say i have:
#include <iostream>
using namespace std;
int **a; //Global Variable
int main()
{
n=5;
a = new int*[n];
for ( int i = 0 ; i < n ; i++ )
a[i] = new int[n] ;
}
is there any realloc() method to increase the row size? (column size is fixed)
I mean if the row size is 5 then i wanna make it 6 not much more, just +1.
I use
for(i=0;i<n;i++)
{
counter++;
a[i] = (int *) realloc(a[i],counter*sizeof(int));
}
but i think something is wrong....
Edit: please don't advise any vector or sth like that.. Cuz i need my array as global.
realloc only works when you allocated with malloc. If you used new, you'll have to delete and then use new again (or just use something like a std::vector).
EDIT: Since you asked for an example of how to use malloc:
a = new int*[n];
would become
a = (int **) malloc (n * sizeof (int *));
and
a[i] = new int[n] ;
would become
a[i] = (int *) malloc (n * sizeof (int));
You can write your own routine to resize the array.
If you want a resized block with size N
allocate (new) the new size N
copy old array/block to this newly allocated array/block
free the old array (delete)
To avoid calling this routine again and again, better preallocate a large chunk, the size of chunk will be determined by the need of your application, and should be such which avoid resizing the array a lot of times.
The answer is No!
C++ memory management does not contain functionality for reallocating/resizing allocated memory. You would have to implement such a thing yourself using new/copy/delete semantics