Swap two arrays without completely allocating a third (C++) - 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

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.

c++ array initialization, good practice

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 ".".

All the members of my array are at the same memory location when they were created using new()

I have created a seven-by-seven array of pointers to "Timeslot" objects in my constructor, using new, like so:
Timeslot ***schedule;
Schedule::Schedule(void)
{
schedule = new Timeslot**[DAYS]();
for(int day = 0; day < DAYS; day++){
schedule[day] = new Timeslot*[TIMESLOTS]();
for(int time = 0; time < TIMESLOTS; time++){
schedule[day][time] = new Timeslot();
}
}
}
When i edit one Timeslot object, the change is made to all of them. I have tried to google this problem, but all instances i could find were people not using new.
Since i was asked, the change i'm making to the timeslot object that is being propagated to all of them is i'm flagging a bit in a bitmask, using a method of the Timeslot class.
void Timeslot::book(int instructor){
bitmask = bitmask | instructormasks[instructor];
}
I have, since posting this question, discovered that yes each timeslot object IS getting its own unique memory address, and somehow the bitmask is being flagged in all of them. I'm looking into it now.
You have a buffer overflow here:
for (int day = 0; day <= DAYS; day++)
schedule[day] = // rest of code
and here
for(int time = 0; time <= TIMESLOTS; time++)
schedule[day][time] = //rest of code
that could be the cause of your problem.
There's no technical problem with your code. No buffer overflows or etc. And, obviously, operator new should return distinct addresses for different objects unless they were explicitly freed.
Then the problem is most probably in the rest of your code.
Are you using a standard heap (new/delete)?
Is bitmask a non-static member of Timeslot class?
Anyway, your code is somewhat over-complicated. It's useful to allocate arrays of pointer-to-pointer-to-pointers in case you're really going to "play" with it, i.e. in runtime re-allocate pointers, or intentionally make several pointers to point on the same object. It's also useful in case you deal with huge objects, and don't want to demand long contiguous memory blocks.
But you say you have in total 7x7 = 49 objects, which are (supposedly) tiny. Then just use one "static" array:
Timeslot schedule[DAYS][TIMESLOTS];
It seems to me like you are defining a 3D array when you need a 2D one.
Timeslot ***schedule; // 3D array
schedule = new Timeslot**[DAYS]() // 2D array of 1D arrays? Or is it the other way around?
I haven't used C arrays for years so I am not sure what the effect of this would be in your initialization loops, but it's worth looking at.
You have a global variable schedule which is initialized in the Schedule constructor.
Maybe you're doing the same thing with bitmask. Make sure that bitmask is a non-static member of Timeslot.

Dynamic array allocation in C++ question

I have a struct of type Duplicate
I have a variable of type int called stringSize, it has a value of 5
I am creating a dynamic array:
Duplicate *duplicates;
duplicates = new Duplicate[stringSize - 1];
Later I delete[] duplicates;
I'm getting one member in that array only? I've verified that stringSize - 1 = 4 with a debug walk through. What can I do to get the 4 members I need?
Any help appreciated,
Thanks // :)
Duplicate *duplicates;
duplicates = new Duplicate[stringSize - 1];
Indeed gives you duplicates[0-3] (Assuming stringSize - 1 is 4, like you say). How are you determining you're getting less?
I suspect you may be doing something like: sizeof(duplicates) / sizeof(duplicates[0]), and on an off-change getting one. The above code only works for statically allocated arrays, where sizeof(duplicates) would match the size of the array, in bytes. In your case, it'll simply return the size of a pointer on your system. (duplicates is a Duplicate*)
And mandatory: Use std::vector if this is "real" code.
Your debugger is doing the best it can. As far is it's concerned, you've merely got a pointer to some data. Consider:
Duplicate foo;
Duplicate *duplicates_A;
duplicates_A = &foo; // points to one Duplicate
Duplicate *duplicates_B;
duplicates_B = new Duplicate[4]; // points to memory containing 4 Duplicate's
bar(duplicates_A);
bar(duplicates_B);
void bar(Duplicate* p)
{
// is p a pointer to one value, or is it an array?
// we can't tell, and this is the same boat your debugger is in
}
How should the debugger, just given a pointer, know if it's pointing to an array or just one value? It cannot, safely. (It would have to determine, somehow, if the pointer was to an array, and the size of that array.)
You can't use sizeof to determine the size of a dynamic array. In fact, there isn't a standard API to determine the size of a dynamic array.
Use std::vector if you need to access the size.
If you use a debugger to view the elements you get, the problem may be that the type of your variable is Duplicate* which is just a pointer (which in C happens to also be an array but the type is just a pointer to one instance of Duplicate.

C++ - is a pointer to a single value same as a size 1 dynamic array?

I have this snippet of code which I am considering to simplfy:
if (numberOfResults > 1)
{
trackResult_ = new TrackResult[numberOfResults];
for (int i=0; i < numberOfResults; i++)
{
// Make a deep copy
TrackResult tempResult = result[i];
TrackResult * clone = new TrackResult(tempResult);
trackResult_[i] = *clone;
}
storeJointResults(trackResult_, numberOfResults);
}
else
{
trackResult_ = new TrackResult(*result);
}
(I have 'no choice' but to use a simple dynamic array here. Vectors are deemed 'too complicated' at my workplace)
I am wondering if I can get away with
// even if we just have one result, we init an array size of one
trackResult_ = new TrackResult[numberOfResults];
However, I have in several points check for the number of results and act accordingly
if (numberOfResults_ == 1)
{
velocity = trackResult_.velocity;
}
Would those code still work? If not, why?
The array of size 1 does not need to be a special case.
When you allocate a dynamic array you are given a pointer to the first element. If the array is of size 1, this is pretty much indistinguishable from just having allocated a single instance of the object.
Your special case usage would work if you changed the . to an ->
However I'd recommend not special-casing it and just use trackResult_[0].velocity
No, you need to ensure you match the correct scalar delete or array delete[] depending on whether you say new TrackResult[n]; or new TrackResult;.
Also, this leaks memory for each loop iteration:
TrackResult tempResult = result[i];
TrackResult * clone = new TrackResult(tempResult);
TrackResult_[i] = *clone;
How are vectors too complicated? If anything, the simplify your code.
I agree with Alex, using the . operator on a pointer is not my recommended style either, so those other points ought to be changed anyhow, and thus not discourage you from simplifying the piece of code you mention.