c++ array initialization, good practice - c++

I would like to be sure that this is not wrong: I initialize array with
double* lower = input->getLowerBox();
where function getLowerBox() returns some double*. is it correct? Or shold I initialize this way::
double* lower = new double[nbP];
for (int i=0;i<nbP;i++)
lower[i]=input->getLowerBox()[i];
or to avoid multiple calls to getLowerBox,
double* lower = new double[nbP];
double* tmp = input->getLowerBox();
for (int i=0;i<nbP;i++)
lower[i]=tmp[i];
delete[] tmp;

Two steps recipe:
Change Input::getLowerBox() to return std::vector<double> const&
Use a copy if you want to modify the returned value, and the const reference instead

Well, it depends on what you want to do. Do you need a new array or not.
Your first snippet doesn't create a new array, so memory management is more important.
For example:
double* lower = input->getLowerBox();
delete[] lower;
would possibly render input->getLowerBox() invalid. Or something like:
double* lower = NULL;
{
Class input;
lower = input->getLowerBox();
}
//...
would make lower a dangling pointer, if input clears the contents of the array in the destructor.
The last two snippets create new arrays. It is safer IMO, but also uses extra memory.
Both are correct, depending on what you want to do. Whichever you choose, make sure to document it fully.

The first way is fine. You're going to return a pointer to a double, which I'm assuming is related to an array (If not, then please correct me). By doing that, you're pointing to the first element of that array and then you can just index lower or use pointer arithmetic to access the other elements.
EDIT: Could you post the definition of getLowerBox() so it's more clear to what you're trying to do?

Do you have the ability to change getLowerBox() ? If so, I would change it so it returns a vector.
Depending on the implementation, it might return you a pointer which you can own or a pointer to an internal static (bad but possible) so you need to know what it's doing and act accordingly by retaining the pointer or taking a copy of the array respectively.
If you don't have control over getLowerBox() and you know the size of the array it returns, it would be a reasonable idea copy it to a vector
double* lower = input->getLowerBox();
vector<double> lowerV(lower, lower + N );
(where N is the size of the array - BTW this is just from memory, I haven't compiled it.)

I would definitely go with the first one for multiple reasons. It's cleaner, it avoids unnecessary calls / variable creation, etc. Just make sure that input's a pointer if you're using "->"; otherwise use ".".

Related

Use of pointer to vector which involved the use of 'new'

I would like to create a vector of pointers to struct
vector<myStruct*> vec
For elements in the vector, not all of them contain data. Some of them may point to NULL.
So, should I create space by new in each of the element first
for(int i = 0; vec.size() ;i++){
if (thisSpaceIsValid(i))
vec.at(i) = new myStruct;
else
vect.at(i) = NULL;
}
The problem comes:
-If I use new for each element, it would be very slow. How can I speed it up a bit? Is there a way the create all the spaces that I need , that automatically access the pointer of such space to the vector(vec here)?
-If later I use delete to free the memory, would the problem of speed still bother me?
If I use "new" for each element, it would be very slow. How can I speed it up a bit? Is there a way the create all the spaces that I need , that automatically access the pointer of such space to the vector("vec" here)?
You can do that.
Let's say the size of your vector is M and you only need N of those elements to have pointers to objects and other elements are null pointers. You can use:
myStruct* objects = new myStruct[N];
and then, use:
for(int i = 0, j = 0; vec.size(); i++)
{
if (thisSpaceIsValid(i))
{
if ( j == N )
{
// Error. Do something.
}
else
{
vec[i] = objects+j;
++j;
}
}
else
{
vect[i] = NULL;
}
}
You have to now make sure that you are able to keep track of the value of objeccts so you can safely deallocate the memory by using
delete [] objects;
PS
There might be a better and more elegant solution to your problem. It will be worth your while to spend a bit more time thinking over that.
EDIT:
After reading the question again, it seems I misunderstood the question. So here is an edited answer.
If you only need to execute the code during some kind of initialization phase, you can create all the instances of myStruct in an array and then just point to those from the vector as already proposed by R Sahu. Note that the solution requires you to create and delete all instances at the same time.
However, if you execute this code several times and/or don't know exactly how many myStruct instances you will need, you could overwrite new and delete for the struct and handle memory allocation yourself.
See Callling object constructor/destructor with a custom allocator for an example of this. See the answer by Jerry Coffin.
BTW - you don't need vec.at(i) as you are iterating from 0 to size. vec[i] is okay and should perform a better.
OLD ANSWER:
You can do
vector<myStruct*> vec(10000, nullptr);
to generate a vector with for instance 10000 elements all initialized to nullptr
After that you can fill the relevant elements with pointer to the struct.
For delete just
for (auto e : vec) delete e;
cause it is safe to do deleteon a nullptr
If you need a vector of pointers, and would like to avoid calling new, then firstly create a container of structs themselves, then assign pointers to the elements into your vec. Be careful with choosing the container of structs. If you use vector of structs, make sure to reserve all elements in advance, otherwise its elements may move to a different memory location when vector grows. Deque on the other hand guarantees its elements don't move.
Multiple small new and delete calls should be avoided if possible in c++ when performance matters a lot.
The more I think about it, the less I like #RSahu's solution. In particular, I feel memory management in this scenario would be a nightmare. Instead I suggest using a vector of unique_ptr's owning memory allocated via custom alloctor. I believe, sequential allocator would do.

Select a random object from an array of objects

I'd like to implement a function that selects a random object from an array of objects and returns it to me. It should be something like (in C++ instead of psuedocode):
getRandomObject(objectList) {
return objectList[int(random(length of objectList))];
}
My current code looks like this, but doesn't seem to work:
//definition of random selector
object getRandomObject(Object* objectList) {
return objectList[int(ofRandom(0, sizeof(objectList)))];
};
//create a pointer for the listOfObjects
object* listOfObjects;
//create an empty object to put the randomly selected object in
object randomObject;
//later in the code, populate the array:
object* listOfObjects[] = {
new Object(),
new Object(),
new Object()
};
//select random object
randomObject = getRandomObject(listOfObjects);
But this seems to return a segmentation fault. A few problems I've noticed:
sizeof() returns the size of the pointer in getRandomObject, not the size of the array. is there a good way to get the size of the array? It might involves not using a float* pointer for the array. Is this a good use case for vectors?
I think that much of the problem lies in how I'm creating my arrays, and not so much in how I'm selecting the random object from them. I'm relatively new to C++ (coming from a Java background), so much of pointers / references / memory management in general is new to me.
thanks!
I see one definite problem and one possible one. The definite problem is that sizeof(objectList) returns the size of the objectList pointer, which will be 4 or 8 on most platforms. It does not return the number of elements in the array, objectList. Either pass in the length of the array or use std::vector or std::array.
The second possible problem relates to ofRandom. Make sure that ofRandom(a,b) returns numbers >= a, but strictly < b. If it returns values <= b, then you'll need to us ofRandom(0, objectVector.size() - 1). Typically, functions like this are written to return values strictly < b, but you should check.
C++ has an array template class that you may want to consider using. Check out the documentation here:
http://www.cplusplus.com/reference/array/array/
This type has a method, size(), that will return the length of the array.
When the sizeof operator is applied to an array, it yields the total
number of bytes in that array, not the size of the pointer represented
by the array identifier.
Quote
So you take the space alocated for your whole array and divide by the memory need just for one element: sizeof(objectList) / sizeof(*objectList).
Mr Fooz noticed issues that cause a segfault.
Other compilation issues are:
listOfObjects is declared with 2 different types: object* and object*[3] while getRandomObject expects a type Object*.
listOfObjects[] contains elements of type object* while getRandomObject reads elements of type Object and returns object.

A better array shifting algorithm?

I have an assignment that requires me to sort a heap based C style array of names as they're being read rather than reading them all and then sorting. This involves a lot of shifting the contents of the array by one to allow new names to be inserted. I'm using the code below but it's extremely slow. Is there anything else I could be doing to optimize it without changing the type of storage?
//the data member
string *_storedNames = new string[4000];
//together boundary and index define the range of elements to the right by one
for(int k = p_boundary - 1;k > index;k--)
_storedNames[k]=_storedNames[k - 1];
EDIT2:
As suggested by Cartroo I'm attempting to use memmove with the dynamic data that uses malloc. Currently this shifts the data correctly but once again fails in the deallocation process. Am I missing something?
int numberOfStrings = 10, MAX_STRING_SIZE = 32;
char **array = (char **)malloc(numberOfStrings);
for(int i = 0; i < numberOfStrings; i++)
array[i] = (char *)malloc(MAX_STRING_SIZE);
array[0] = "hello world",array[2] = "sample";
//the range of data to move
int index = 1, boundary = 4;
int sizeToMove = (boundary - index) * sizeof(MAX_STRING_SIZE);
memcpy(&array[index + 1], &array[index], sizeToMove);
free(array);
If you're after minimal changes to your approach, you could use the memmove() function, which is potentially faster than your own manual version. You can't use memcpy() as advised by one commenter as the areas of memory aren't permitted to overlap (the behaviour is undefined if they do).
There isn't a lot else you can do without changing the type of your storage or your algorithm. However, if you change to using a linked list then the operation becomes significantly more efficient, although you will be doing more memory allocation. If the allocation is really a problem (and unless you're on a limited embedded system it probably isn't) then pool allocators or similar approaches could help.
EDIT: Re-reading your question, I'm guessing that you're not actually using Heapsort, you just mean that your array was allocated on the heap (i.e. using malloc()) and you're doing a simple insertion sort. In which case, the information below isn't much use to you directly, although you should be aware that insertion sort is quite inefficient compared to a bulk insert followed by a better sorting algorithm (e.g. Quicksort which you can implement using the standard library qsort() function). If you only ever need the lowest (or highest) item instead of full sorted order then Heapsort is still useful reading.
If you're using a standard Heapsort then you shouldn't need this operation at all - items are appended at the end of the array, and then the "heapify" operation is used to swap them into the correct position in the heap. Each swap just requires a single temporary variable to swap two items - it doesn't require anything to be shuffled down as in your code snippet. It does require everything in the array to be the same size (either a fixed size in-place string or, more likely, a pointer), but your code already seems to assume that anyway (and using variable length strings in a standard char array would be a pretty strange thing to be doing).
Note that strictly speaking Heapsort operates on a binary tree. Since you're dealing with an array I assume you're using the implementation where a contiguous array is used where the children of node at index n are stored at indicies 2n and 2n+1 respectively. If this isn't the case, or you're not using a Heapsort at all, you should explain in more detail what you're trying to do to get a more helpful answer.
EDIT: The following is in response to you updated code above.
The main reason you see a problem during deallocation is if you trampled some memory - in other words, you're copying something outside the size of the area you allocated. This is a really bad thing to do as you overwrite the values that the system is using to track your allocations and cause all sorts of problems which usually result in your program crashing.
You seem to have some slight confusion as to the nature of memory allocation and deallocation, first of all. You allocate an array of char*, which on its own is fine. You then allocate arrays of char for each string, which is also fine. However, you then just call free() for the initial array - this isn't enough. There needs to be a call to free() to match each call to malloc(), so you need to free each string that you allocate and then free the initial array.
Secondly, you set sizeToMove to a multiple of sizeof(MAX_STRING_SIZE), which almost certainly isn't what you want. This is the size of the variable used to store the MAX_STRING_SIZE constant. Instead you want sizeof(char*). On some platforms these may be the same, in which case things will still work, but there's no guarantee of that. For example, I'd expect it to work on a 32-bit platform (where int and char* are the same size) but not on a 64-bit platform (where they're not).
Thirdly, you can't just assign a string constant (e.g. "hello world") to an allocated block - what you're doing here is replacing the pointer. You need to use something like strncpy() or memcpy() to copy the string into the allocated block. I suggest snprintf() for convenience because strncpy() has the problem that it doesn't guarantee to nul-terminate the result, but it's up to you.
Fourthly, you're still using memcpy() and not memmove() to shuffle items around.
Finally, I've just seen your comment that you have to use new and delete. There is no equivalent of realloc() for these, but that's OK if everything is known in advance. It looks like what you're trying to do is something like this:
bool addItem(const char *item, char *list[], size_t listSize, size_t listMaxSize)
{
// Check if list is full.
if (listSize >= listMaxSize) {
return false;
}
// Insert item inside list.
for (unsigned int i = 0; i < listSize; ++i) {
if (strcmp(list[i], item) > 0) {
memmove(list + i + 1, list + i, sizeof(char*) * (listSize - i));
list[i] = item;
return true;
}
}
// Append item to list.
list[listSize] = item;
return true;
}
I haven't compiled and checked that, so watch out for off-by-one errors and the like, but hopefully you get the idea. This function should work whether you use malloc() and free() or new and delete, but it assumes that you've already copied the string item into an allocated buffer that you will keep around, because of course it just stores a pointer.
Remember that of course you need to update listSize yourself outside this function - this just inserts an item into the correct point in the array for you. If the function returns true then increment your copy of listSize by 1 - if it returns false then you didn't allocate enough memory so your item wasn't added.
Also note that in C and C++, for the array list the syntax &list[i] and list + i are totally equivalent - use the first one instead within the memmove() call if you find it easier to understand.
I think what you're looking for is heapsort: http://en.wikipedia.org/wiki/Heapsort#Pseudocode
An array is a common way to implement a binary search tree (i.e. a tree in which left children are smaller than the current node and right children are larger than the current node).
Heapsort sorts an array of a specified length. In your case, since the size of the array is going to increase "online", all you need to do is to call change the input size that you pass to heapsort (i.e. increase the number of elements being considered by 1).
Since your array is sorted and you can't use any other data structure your best bet is likely to perform a binary search, then to shift the array up one to free space at the position for insertion and then insert the new element at that position.
To minimise the cost of shifting the array, you could make it an array of pointers to string:
string **_storedNames = new string*[4000];
Now you can use memmove (although you might find now that an element-by-element copy is fast enough). But you will have to manage the allocation and deletion of the individual strings yourself, and this is somewhat error-prone.
Other posters who recommend using memmove on your original array don't seem to have noticed that each array element is a string (not a string* !). You can't use memmove or memcpy on a class like this.

Swap two arrays without completely allocating a third (C++)

I have two arrays of type Region, both of size 1000, and at every iteration of a loop I want to swap the two of them (by swapping their memory addresses). I was hoping this would work:
Region *swap = (Region*)myRegions;
myRegionsLast = myRegions;
myRegions = (Region[1000])swap;
Line one seems fine. The second and third lines are invalid assignments, as you apparently can't re-assign that type. The third line is also invalid because you can't cast to the type (Region [1000]). Obviously I don't want to allocate whole new Region[1000] if I can help it. Can someone help me accomplish what I want?
This happens because you cannot assign a whole array at once. You can assign a pointer, however:
Region reg1[1000], reg2[1000];
Region *myRegionsLast = reg1;
Region *myRegions = reg2;
Now your swap routine is going to work without further modifications.
You could also swap arrays one element at a time, but it is going to involve a lot more data copying.
How about creating just a variable of the content of Region type and iterating through it...
for(int i=0; i<1000; i++)
{
tempRegionTypeVariable = myRegionsLast[i];
myRegionsLast[i] = myRegions[i];
myRegions[i] = tempRegionTypeVariable;
}
Hope this helps..
Here "tempRegionTypeVariable" is just a temporary variable or an Object. Not an Array..
A couple other valid answers were posted in the comments:
Use std::swap() / std::array::swap
Make them dynamically allocated arrays instead of static

C++ How can I iterate till the end of a dynamic array?

suppose I declare a dynamic array like
int *dynArray = new int [1];
which is initialized with an unknown amount of int values at some point.
How would I iterate till the end of my array of unknown size?
Also, if it read a blank space would its corresponding position in the array end up junked?
Copying Input From users post below:
Thing is:
a) I'm not allowed to use STL (means: no )
b) I want to decompose a string into its characters and store them. So far I wanted to use a function like this:
string breakLine (string line){
int lineSize = line.size();
const char *aux;
aux=line.data();
int index=0;
while (index<=lineSize){
mySynonyms[index]=aux[index];
index++;
}
I thought that the array aux would end up junked if there was a large blank space between the two numbers to be stored (apparently not). And I was wondering if there was a way to iterate till an undefined end in this type of array. Thanks for you answers.
You don't: wrap the array into a structure that remembers its length: std::vector.
std::vector v(1);
std::for_each( v.begin(), v.end(), ... );
No portable way of doing this. Either pass the size together with the array, or, better, use a standard container such as std::vector
Short answer is that you can't. If you have a pointer to the first element of an array, you can't know what the size of the array is. Why do you want to use a array in the first place. You would be much better off using a std::vector if your array can change size dynamically, or a boost::Array if it will be a fixed size.
I don't understand your second question.
Your code needs to keep to track of the array, so the size would never be unknown. (Or you would have to use some library with code that does this.)
I don't understand the last part of your quesiton. Could you elaborate?
You explained in your post below that you want to look at the guts of a std::string.
If you are expecting your stirng to be like a c-string (aka doesn't contain NULLs), then use line.c_str() instead of line.data(). This will guarantee that aux points to a null terminates c-style string.
After that you can iterate until aux[index] == '\0';
Otherwise, you can use line.data() and string.length/size to get it's size like in your example.
However, "decomposing a string into its characters" is pretty pointless, a string is an array of characters. Just make of copy of the string and store that. You are allowed to do:
char ch = line[index];
Better yet, use iterators on the original string!
for(std::string::const_iterator it = line.begin(); it != line.end(); ++it) {
const char ch = *it;
// do whatever with ch
}
a) I'm not allowed to use STL (means:
no )
What?? Who's moronic idea was that?
std::vector isn't part of the "STL" (which is a copyrighted product of HP), but is (and has been for nearly a decade) part of the C++ Language Standard.
If you're not allowed to use the STL (for whatever reason), the first thing you want to do is actually to implement your own version of it – at least the parts you need, with the level of customizability you need. For example, it's probably overkill to make your own vector class parametrizable with a custom allocator. But nevertheless do implement your own lightweight vector. Everything else will result in a bad, hardly maintainable solution.
This smells like homework, and the teacher's objective is to give you a feeling of what it takes to implement dynamic arrays. So far you're getting an F.
You need to realize that when you allocate memory like this
int *dynArray = new int [1];
you allocate precisely one integer, not an indefinite number of integers to be expanded by some unidentified magic. Most importantly, you can only say
dynArray[0] = 78;
but you cannot say
dynArray[1] = 8973;
The element at index 1 does not exist, you're stepping into memory that was not reserved for you. This particular violation will result in a crash later on, when you deallocate the array, because the memory where you stored 8973 belongs to the heap management data structures, and you corrupted your heap.
As many other responders mention, you must know how many elements you have in the array at all times. So, you have to do something along the lines of
int arraySize = 1;
int *dynArray = new int [arraySize];
arraySize goes together with the array, and is best combined with dynArray in one C++ object.
Now, before you assign to dynarray[1], you have to re-allocate the array:
if (index > arraySize) {
int newSize = index+1;
int *newArray = new int[newSize]
// don't forget to copy the data from old array to new
memcpy(newarray dynArray, sizeof *newArray * arraySize);
arraySize = newSize;
dynArray = newArray;
}
// now you're ready!
dynArray[index] = value;
Now, if you want to make it a bit more efficient, you allocate more than you need, so you don't have to allocate each time you add an element. I'll leave this as an exercise to the reader.
And after doing all this, you get to submit your homework and you get to appreciate the humble std::vector that does all of this for you, plus a lot more.
Use a vector, which has a vector.size() function that returns an integer and a vector.end() function that returns an iterator.
You could create a simple Vector class that has only the methods you need. I actually had to recreate the Vector class for a class that I took this year, it's not very difficult.
If there's a value that cannot be valid, you can use that as a sentinel, and make sure all of your arrays are terminated with that. Of course, it's error-prone and will cause hard-to-find bugs when you happen to miss doing it once, but that's what we used to do while reading files in FORTRAN (back in the all-caps days, and before END= became standard).
Yes, I'm dating myself.