C++ Pointer of Array of Ints Initialization - c++

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!

Related

Shrinking the size of a dynamically allocated array in C++ [duplicate]

I have created an array pointer as a global variable like this:
T *bag;
bag = new T[size];
I have a method where I insert things into the array; however, if it detects that it will overflow the array, I need to resize the array (without vectors). I've been reading about this question all over stack overflow but the answers don't seem to apply to me because I need the data from the old array copied into the new array. Additionally, if I create a new array of a larger size inside the method and then copy the data over to the new array, once the method ends, the array will disappear, but I need it to be a global variable again so all my methods can see it...How should I proceed?
Thank you
Memory, allocated by new, would not disappear after your method ends.
You can return pointer to a new array by usung reference: void f(int *&ptr, size_t &size).
Also, be aware, that you need to clear memory manually arter you use it. For example:
int* newArray = new int[newSize];
... copying from old array ...
int* temp = oldArray;
oldArray = newArray;
delete[] temp;
To resize an array you have to allocate a new array and copy the old elements to the new array, then delete the old array.
T * p_bag;
p_bag = new T[old_size];
//...
T * p_expanded_bag = new T[new_size];
for (unsigned int i = 0; i < old_size; ++i)
{
p_expanded_bag[i] = p_bag[i];
}
delete[] p_bag;
p_bag = p_expanded_bag;
You could use std::copy instead of the for loop.
The thing you need can do the following things
Automatically handle the resizing when requested size is larger than current array size.
When resizing, they can copy the original content to the new space, then drop the old allocation immediately .
There is a non-global-variable way mechanism they can track the array pointer and the current size.
The thing is very similar to std::vector. If it is not allowed to use, you may need manage a dynamic allocated resource like std::vector on your own. You can reference the implementation in that answer link.
If eventually you need to wrap it in a class, make sure to follow the big 3 rules (5 rules in C++11)
You can use realloc from c if you have array of chars/ints/doubles... or some other fundamental data type or classes with only those variables (eg. array of strings won't work).
http://www.cplusplus.com/reference/cstdlib/realloc/
bag = (T*) realloc(bag, new_size * sizeof(T));
Realloc automatically allocate space for your new array (maybe into the same place in memory) and copy all data from given array.
"The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location."
Example:
#include <stdio.h> /* printf*/
#include <stdlib.h> /* realloc, free */
#include <iostream>
int main()
{
int old_size = 5;
int new_size = 10;
int *array = new int[old_size];
printf("Old array\n");
for (int i=0; i<old_size; i++) {
array[i] = i;
printf("%d ", array[i]);
}
printf("\nArray address: %d\n", array);
array = (int*) realloc(array, new_size * sizeof(int));
printf("New array\n");
for (int i=0; i<new_size; i++)
printf("%d ", array[i]);
printf("\nArray address: %d\n", array);
free(array);
return 0;
}

What does this code do? (c++, classes and arrays)

IntArray::IntArray (int *array, int sz)
{
_size = sz;
int ia = new int[_size];
for (int ix=0; ix<_size; ++ix)
ia[ix] = array[ix];
}
Hello, I'm currently studying C++ for beginners by Stanley Lipmann and I'm going through creating of abstract arrays with Classes help. Can someone explain me what does this code do? By my guess it assigns "sz" value (from outside of class) to "_size", then we create the "ia" dynamic array and after all it assigns values from "array" pointer (that outside of class) to an "ia" array. Thanks :D
That cannot be the full code, where is _size defined? Is it a class member? The leading underscore suggests that. I presume that ia is also a class member of type int *.
What it does is to copy the value of sz into the (presumably) member variable _size. Then it allocates a new array of int. The for loop then copies the elements from the given array into the new memory allocated. Looking at the name it will tell you that this is a constructor. It constructs a new array of ints by copying the given array.
And by the way, indent your code such that it is easier to read, that will make understanding it easier!
IntArray::IntArray(int *array, int sz) {
_size = sz;
ia = new int[_size];
for (int ix = 0; ix < _size; ++ix)
ia[ix] = array[ix];
}
You can use the amazing clang-format for all your formatting needs.
You can throw in a const to the array and sz parameters, that way you can also create new IntArray instances from constant arrays.

how can I copy an array from a class and double the size of the new array?

CDCatalogue::CDCatalogue() //creates array of size 4
{
maxsize=4;
numcds = 0;
cds = new CD[maxsize];
}
I want this to copy cat into a new array with double the size of cat:
CDCatalogue::CDCatalogue(const CDCatalogue& cat)
{
}
As suggested before I'd prefer to use std::vector, which offers the resize() member function for exactly what you need. This is probably what you are looking for.
If for some reason you cannot use vectors, maybe a simpler approach than having a "doubler copy constructor" would be having a function 'doubleSize' that you can call right after construct-copying.
Assuming that in your example in the question, maxsize and cds are declared as class members, you could do something like this:
CDCatalogue::doubleSize() {
unsigned int oldMaxSize = maxsize;
maxsize *= 2; // You might want to keep an eye for overflows here
CD *oldCds = cds;
cds = (CD*) new CD[maxsize];
std::copy(oldCds, oldCds+oldMaxSize, cds);
delete[] cds;
}
Note that this is not as simple as using vectors, because there is no "resize" for c++ dynamic allocations. Instead, you have to create a new array of the new desired size, copy the elements of the old array into the new, and then release the memory of the old array. Note that the last half of elements of the new array will be initialized to undefined values.

Create dynamic array based on an array returned by a function

I'm currently trying to learn C++, and one of the training exercises I'm doing asks that I do the following:
Create a dynamic array, add 100 int values to it.
Write a function that calculates the square of each array element, and save this int value as position 100 + element_index in the array.
At the current moment I have created a dynamic array and filled it with pseudo-random values. What I want to do is to calculate the square of these random values, and "append" them at the end of the array.
The variable firstArray is defined earlier, but is set to be 100.
typedef int* intPtr;
...
...
srand((unsigned)time(0));
intPtr myArray;
myArray = new int[firstArray];
for (int i = 0; i < firstArray; i++)
ptr[i] = (rand() % 10);
This creates my initial dynamic array, and gives each location in the array a random value between 0 and 10.
If I don't have to use a function, I can easily create a new dynamic array, copy the first 100 values in, and then calculate the squares and place them at the end. I have an attempt at some pseudo-code for the exercise, but I'm unsure as how to properly implement it.
Create dynamic array of size 100, called myArray
Fill each indexed location with a random value between 0 and 10
Pass the dynamic array into a function
Function creates a new dynamic array of size 200
The values on location 0-99 from myArray are copied over
Calculate the square of the value on location n, and write it to location n+100
Return the dynamic array
Delete [] myArray
Create new dynamic array of size 200, called myArray
Copy the values from the array returned by my function into myArray
Delete the array returned from my function
My question relates to passing the information into a function, and returning the new information:
How do I create a function that I can pass a dynamic array into, and have it return another dynamic array?
If it is not possible to have this question answered, I would also very much like feedback on structure, information included in the question and if this is not the right type of question to ask, so I can ask better questions in the future.
Function that takes a dynamic array and returns a dynamic array (of ints) would have this signature:
int* newArray(int* array, int size);
An implementation would then start with:
int* newArray(int* array, int size)
{
int* ret = new int[size * 2]; // double the size
// stuff to populate ret
return ret;
}
int* myBiggerArray = newArray(myArray, firstArray);
// use myBiggerArray
delete [] myBiggerArray;
Also, stay away from typedefing things like int*. int* is already clear and concise enough.
I don't see any requirement that the array needs to be allocated twice. You can allocate all the memory once.
// Allocate all the memory.
intPtr myArray = new int[firstArray*2];
// Fill the first part with random numbers
for (int i = 0; i < firstArray; i++)
ptr[i] = (rand() % 10);

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>>();