Is it possible to swap arrays of structs (in linear time)? - c++

I have a small program computing the forces of planets on each other. My program has two arrays of structs, one that holds the positions and velocities before iterations, and the other holds what their positions and velocities will be after the iterations.
At the end of each iteration, I'd like to move the values from the second array into the first and the second array can become garbage (but needs to point to some valid memory location I can write to later). I thought I could simply switch the arrays since an array is a pointer, but the compiler won't let me.
Consider this example:
typedef struct { int a; } Foo;
int main()
{
Foo bar[8], baz[8];
Foo *temp = baz;
baz = bar; //ISO C++ forbids the assignment of arrays
bar = temp; //incompatible types in assignment of Foo* to Foo[8]
}
This is what I'd like to do. It would certainly be faster than a for loop from 1 to N.

You should consider using std::vector which can be swapped in constant time:
std::vector<Foo> bar(8), baz(8);
std::swap(bar, baz);
Or if you don't want to do that and instead want to manually manage your memory, you can use new[] to get a pointer to an array on the free store and swap the pointers when you want to swap the arrays.
If you must have your arrays on the stack, the only way to do this without actually swapping each element would be to create the arrays on the stack and instead of using the arrays, use pointers to the arrays:
Foo bar[8], baz[8], *pbar = bar, *pbaz = baz;
// ...
// this code only using pbar and pbaz
// ...
// swap the pointers
std::swap(pbar, pbaz);
// ...
// use pbar and pbaz some more
// ...

Here's where you went wrong:
since an array is a pointer
This is not true. Arrays decay to a pointer, but they are not the same thing.
However you can easily do what you want here by actually getting pointers from those arrays.
Foo bar[8], baz[8];
// load bar up with valid data
Foo *data = bar;
Foo *garbage = baz;
// compute next step
std::swap(data,garbage);
Also consider using std::array rather than raw arrays (it has properties more consistent with other types in C++ and is less 'special' than raw arrays). Then when you use pointers to these arrays the size of the array won't be discarded the way it is for pointers to raw arrays.
std::array<Foo,8> bar, baz;
std::array<Foo,8> *data = &bar;
std::array<Foo,8> *garbage = &baz;
// compute next step
std::swap(data,garbage);
If you need dynamically sized arrays use std::vector, and then you can just swap the vectors directly rather than swapping pointers to the vectors, because swapping vectors will be implemented to swap the pointers inside the vectors.
std::vector<Foo> data, garbage;
// compute next step
std::swap(data,garbage);

The problem is that you're using a stack-allocated array.
When you say Foo bar[8];, you're creating space for eight Foo structs in the current stack frame. So the reason you can't assign it to something else is that it'd have to move outside the frame somehow, escaping the memory management and scoping it's supposed to have.
You want a dynamically-allocated array - Foo* bar = new Foo[8];. When you're done with it, delete[] bar;. The difference here is that now the pointer is on the stack, but the actual contents are on the heap - so you can change the location the pointer references without having to worry about moving the actual pointer itself.
Another option is to use a class with a copy-constructor and operator=, like std::vector, std::list, or std::deque.
Incidentally, the procedure of copying the array contents is linear time. A pointer assignment is constant time (O(1)) because it doesn't matter how large your array gets - it's always one operation to move the pointer.

You could use memcpy:
int main()
{
Foo bar[8], baz[8], temp[8];
memcpy(temp, baz, sizeof(Foo) * 8);
memcpy(baz, bar, sizeof(Foo) * 8);
memcpy(bar, temp, sizeof(Foo) * 8);
}

You can declare your arrays as temps, and also declare pointers - which you will use for the rest of the function.
Those ponters can be easily swapped.
int main()
{
Foo temp1[8], temp2[8];
Foo *bar = temp1, *baz = temp2;
Foo *temp = baz;
baz = bar; //no problems now
bar = temp;
}

Foo bar[8], baz[8];
Then
Foo* arr1 = bar, arr2 = bax;
Forget about baz & bar, work only with arr1 and arr2.
Swap:
int* temp = arr1;
arr1 = arr2;
arr2 = temp;

Related

Array of objects vs new

#include <iostream>
class A {
public:
A(int d) : y(d) {}
int y;
};
int main(void) {
A d[3] = {A(0), A(1), A(2)};
std::cout << d[1].y << std::endl;
};
I'm working on a project for university. I'm instructed not to use an object array and instantiate each element with a temporary object of my class - so something like the above code is a no-no. Instead, it's recommended we use a an array of type A* and then use new on each element so that we create an object and make each element point to it.
So we'd have something like this:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
However, I don't quite understand the difference in practice when compared to the first version. As far as I understand in the first version we we create the three temporary objects (which are rvalues) using the constructor and then assign them to the array. After the assignment ends, the temporary is destroyed and its values are copied to the array. In the second version, we have the advantage of being able to delete what d[] points to but disregarding that, what is the drawback of using the first method?
EDIT:
class B{
public:
A a1[3];
}
Assuming my initial definition is followed by this (A isn't default constructible, is something like this impossible? So in that case I can't an array of objects and I instead have to resort to a pointer array of type A* and then use new, as my only resort.
Array of pointers -> memory allocation when you create an object and assign it to the pointer. Array of 1000 pointers with 1 element inside = 1x the memory.
Array of objects -> memory allocation when you create an array. Array of 1000 with 1 element inside = 1000x the memory.
1 ) A d[3], it creates a built-in array (or C-style, plain, naked array...) which contains (three) elements of type A, these elements live on the stack (according to your code).
2 ) A* d[3];, it creates a built-in array which contains (three) pointers to elements of type A (or they should). It doesn't mean that the pointed element is of type A, it's developer's task to create those elements, and you can do it in two ways, using the stack (as before):
A element;
...
d[0] = &element;
or using the heap (with new/new[] and delete/delete[]):
d[0] = new A;
...
delete d[0];
Side effects of the second option; you may point to an already destroyed element (i.e. the element is out of scope), hence potential seg fault; you may loose the pointer to the allocated memory (i.e. the array of pointers is out of scope and the allocated memory has not been released), hence memory leak.
However, an advantage is that you can use lazy initialisation (you don't pay for what you don't use). If you don't need an A object in d[2] (or pointed by), why should you create it and waste memory? And here smart pointers arise, they make your life easier allowing you to allocate memory only when you need it, reducing the risk of seg faults (worth it to mention std::weak_ptr), memory leaks, etc:
std::unique_ptr<A> d[3];
d[0] = std::make_unique<A>(); // Call make_unique when you need it
But still a bit nasty, the built-in arrays are good but may be much better under some circumstances. It is hard to add or remove elements, iterate, get the size, access to the tail/head, etc... And that's why containers are quite useful, i.e. std::array or std::vector (where its size doesn't have to be known at compilation time):
std::vector<std::unique_ptr< A> > d(3);
std::array<std::unique_ptr<A,3> > d;
There are no advantages whatsoever to the following code in C++:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
In fact, you shouldn't write it at all.
Your solution with a locally-declared temporary array is valid, but has the significant limitation of requiring that the number of elements in the array be a compile-time constant (i.e., known ahead of time).
If you need to have an array with a dynamic number of elements, known only at run time, then you should use a std::vector, which performs the new allocation automatically. That is the idiomatic way of working with dynamically-allocated arrays in C++.

How to make an array that holds unique_ptrs?

I am under the assumption that the code bellow is a unique_ptr to an array (aka not what I want)
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
arr[0] = *new int(1);
delete &arr[0]; // malloc error, want to avoid "delete"
However, I want an array that holds unique_ptrs like so...
std::unique_ptr<int> arr2 []; //Error, requires explicit size
arr2 = std::make_unique<int> [5]; //Desirable, does not compile
arr2[0] = std::make_unique<int>(1); //Desirable, does not compile
How do I go about making an array of unique_ptrs? If that is not possible, then how do I deal with a malloc error?
Do you want an array that holds unique_ptrs (as in the title), or a unique_ptr holding an array (as in your examples)?
If an array of unique_ptrs is what you want, then
std::vector<std::unique_ptr<int>>
or
std::array<std::unique_ptr<int>, 3>;
(for example) will do the job.
If a unique_ptr holding an array is what you're after, then unique_ptr<int[]> will work (there is a partial specialisation of unique_ptr to support it), although you can't use std::make_unique and will need to call operator new[] yourself:
std::unique_ptr<int[]> p{new int[42]};
However, if you think you need this, what you most likely really want is std::vector, and I'd strongly recommend using that instead.
Short answer: use vectors. They are much easier to work with and you don't have to explicidly allocate memory. You should also use typedefs for syntax simplicity.
typedef unique_ptr<int> intPtr;
vector<intPtr> vec;
vec.push_back(make_unique<int>(69));
auto myIntPtr = make_unique<int>(16);
vec.push_back(move(myIntPtr)); // unique ptrs cannot be copied, must be moved
unique_ptr<int[5]> p1; // valid syntax
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
At this point you have a unique_ptr to an array of int. This sounds like it is exactly what you want.
arr[0] = *new int(1);
But this is questionable. It dynamically allocates a single int, assigns 1 to the allocated int, then it assigns the value, 1, at the allocated int into the array at element 0. the allocated int is left hanging with nothing pointing at it, and is now exceptionally difficult to `delete. This is a memory leak.
delete &arr[0]; // malloc error, want to avoid "delete"
And as you've seen, this is fatal. Rather than attempting to delete the leaked int, delete has been invoked with a pointer to the array stored in the unique_ptr. Eventually the unique_ptrwill try todelete` the array and fail because it's already gone.
Based on comments, OP intends
std::unique_ptr<int*[]> arr;
arr = std::make_unique<int*[]> (5);
arr[0] = new int(1);
delete arr[0];
But I'd like to talk them out of this idea. Let's look at their end goal: a templated class
template <class TYPE>
class MyVector
{
std::unique_ptr<TYPE[]> arr; // array of whatever type
public:
MyVector(size_t size): arr(std::make_unique<TYPE[]> (size))
{
}
TYPE& operator[](size_t index)
{
return arr[index];
}
// note the complete lack of growing, shrinking and other vector goodness
// as they are not needed for this example.
};
We can use this class with just about anything.
int main()
{
// vector of int
MyVector<int> vec(5);
vec[0] = 1;
// vector of pointer to int (yuck)
MyVector<int*> vec2(5);
vec2[0] = new int(1);
delete vec2[0];
// vector of smart pointer to int (also yuck, but less yuck)
MyVector<std::unique_ptr<int>> vec3(5);
vec3[0] = std::make_unique<int>(1);
// vector of std::string
MyVector<std::string> vec4(5);
vec4[0] = "I am the very model of a modern major general...";
}
If the user of the vector want it to contain pointers, they can say so. There is no reason to force the user to use a pointer.

Is memory freed when dynamic array goes out of scope

I am dynamically allocating memory for an array in a function. My question is: once the function finishes running is the memory freed?
code:
void f(){
cv::Mat* arr = new cv::Mat[1];
...
}
No, memory allocated using new is not automatically freed when the pointer goes out of scope.
However, you can (and should) use C++11's unique_ptr, which handles freeing the memory when it goes out of scope:
void f(){
std::unique_ptr<cv::Mat[]> arr(new cv::Mat[1]);
...
}
C++11 also provides shared_ptr for pointers you might want to copy. Modern C++ should strive to use these "smart pointers", as they provide safer memory management with almost no performance hit.
No, it is not. You must free it by calling
delete[] arr;
But you should ask yourself whether it is necessary to allocate dynamically. This would require no explicit memory management:
void f(){
cv::Mat arr[1];
...
}
If you need a dynamically sized array, you could use an std::vector. The vector will internally allocate dynamically, but will take care of de-allocating it's resources:
void f(){
std::vector<cv::Mat> arr(n); // contains n cv::Mat objects
...
}
No. Every call to new needs to be matched up with a call to delete somewhere.
In your case arr iteself is a variable with automatic storage duration. This means that arr itself will be destroyed when it goes out of scope. However the thing that arr points to does not, because that is a variable that does not have autoatic storage duration.
The fact that arr itself has automatic storage duration can be used to your advantage, by wrapping the raw pointer in a class that destroys the stored pointer when the automatic object is destroyed. This object utilizes an idion known as RAII to implement a so-called "smart pointer". Since this is a very common requirement in well-designed applications, the C++ Standard Library provides a number of smart pointer classes which you can use. In C++03, you can use
std::auto_ptr
In C++11 auto_ptr has been deprecated and replaced by several other better smart pointers. Among them:
std::unique_ptr
std::shared_ptr
In general, it is a good idea to use smart pointers instead of raw ("dumb") pointers as you do here.
If what you ultimately need are dynamically-sized arrays, as supported by C99, you should know that C++ does not have direct support for them. Some compilers (notably GCC) do provide support for dynamically sized arrays, but these are compiler-specific language extensions. In order to have something that approximates a dynamically sized array while using only portable, Standards-compliant code, why not use a std::vector?
Edit: Assigning to an array:
In your comments you describe the way in which you assign to this array, which I have taken to mean something like this:
int* arr = new int[5];
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
If this is the case, you can accomplish the same using vector by calling vector::operator[]. Doing this looks uses very similar syntax to what you've used above. The one real "gotcha" is that since vectors are dyanamically sized, you need to make sure the vector has at least N elements before trying to assign the element at position N-1. This can be accomplished in a number of ways.
You can create the vector with N items from the get-go, in which case each will be value-initialized:
vector<int> arr(5); // creates a vector with 5 elements, all initialized to zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
You can resize the vector after the fact:
vector<int> arr; // creates an empty vector
arr.resize(5); // ensures the vector has exactly 5 elements
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
Or you can use a variety of algorithms to fill the vector with elements. One such example is fill_n:
vector<int> arr; // creates empty vector
fill_n(back_inserter(arr), 5, 0); // fills the vector with 5 elements, each one has a value of zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
No, of course not.
For every new you need precisely one delete.
For every new[] you need precisely one delete[].
Since you don't have the matching delete[], your program is broken.
(For that reason, the adult way of using C++ is not to use new or pointers at all. Then you don't have those problems.)
No. The array the allocated on the heap, you'll have to delete it before it goes out of scope:
void f() {
cv::Mat * arr = new cv::Mat[1];
// ...
delete [] arr;
}

Set array of object to null in C++

Suppose I have an array of objects of type Foo in C++:
Foo array[10];
In Java, I can set an object in this array to null simply by:
array[0] = null //the first one
How can I do this in C++?
Use pointers instead:
Foo *array[10];
// Dynamically allocate the memory for the element in `array[0]`
array[0] = new Foo();
array[1] = new Foo();
...
// Make sure you free the memory before setting
// the array element to point to null
delete array[1];
delete array[0];
// Set the pointer in `array[0]` to point to nullptr
array[1] = nullptr;
array[0] = nullptr;
// Note the above frees the memory allocated for the first element then
// sets its pointer to nullptr. You'll have to do this for the rest of the array
// if you want to set the entire array to nullptr.
Note that you need to consider memory management in C++ because unlike Java, it does not have a Garbage Collector that will automatically clean up memory for you when you set a reference to nullptr. Also, nullptr is the modern and proper C++ way to do it, as rather than always is a pointer type rather than just zero.
So, forget Java here, it's not helping you. Ask yourself; what does it mean for an object to be null? Can an object be null? The answer is no, an object can not be null, but a reference (pointer in C++ terms) to one can be.
In java you have reference types, which are similar to pointers under the hood. However, you cannot set objects to null even in java, only references.
In C++ you have fully fledged objects and pointers and references to objects. A pointer to an object (or primitive type) can be null, but an object itself cannot.
So, when you create an array of Foo objects you have, well, an array of Foo objects. You don't have pointers, you have objects. If your array were an array of pointers to objects then yes, you could initialize them to null (nullptr in C++0x), i.e., they don't refer to a valid object.
Other way that you have is using one dynamic array of pointers of Foo like this:
Foo** array = new Foo*[10];// Pointer of array of pointers.
Then you can initialize all this pointers to objects Foo
for(int i=0;i<10;i++)
array[i] = new Foo();// Give memory to pointers of object Foo in array
assign null to one item of array:
array[0] = 0;
I think that in C++, NULL is 0. This means it can even be assigned to an int or anywhere a 0 is acceptable. Conventionally, it's only used with pointers.
For delete this memory:
for(int i=0;i<10;i++)
delete array[i];
and finally
delete[] array;
Code Example:
#include <iostream.h>
#include <stdio.h>
class Foo
{
private:
int a;
public:
Foo()
{
a = 0;
}
void Set_V(int p){a = p;}
int Get_V(){return a;}
};
int main()
{
Foo **array = new Foo*[10];
for(int i=0;i<10;i++)
{
array[i] = new Foo();
}
//array[0] = 0;
for(int i=0;i<10;i++)
array[i]->Set_V(i);
for(int i=0;i<10;i++)
cout<<array[i]->Get_V()<<endl;
for(int i=0;i<10;i++)
delete array[i];
delete[] array;
return 0;
}
so is there away to "remove" an element in the array without creating a new one? i.e making a hole in the array of some sort?
In C++, if you have an array:
Foo array[10];
Then all 10 elements will be default-constructed. In general, there's no concept of array elements being in use vs. "removed". One way to track this idea is to make having actual values in the array elements optional, as in:
boost::optional<Foo> array[10];
You can read about the boost library's optional<> library at http://www.boost.org/doc/libs/release/libs/optional/
For the sake of documenting alternatives, I'll cover a hideous one. You could call the destructor on one of the elements: array[3].~Foo(); This is very dangerous as when the array itself goes out of scope, the destructor for each element will be called, and a precondition for that is to have a properly constructed object, so you have to be sure to have constructed a Foo in that element again beforehand (using "placement" new). There is nothing in the array itself that will help you keep track of which elements have had their destructors called by you - you'd need to track that yourself (having some record of this inside the objects would probably work in practice, but accessing the object after destruction is undefined behaviour). You'd need to be very careful that in all code paths - including those due to exceptions - you tracked the momentarily unused array elements. You really don't want to do this.
If your concern is to remove an element from the array to save memory, then use smart pointers:
shared_ptr<Foo> array[10];
You can then control specific array elements independently, with only still-populated elements being destructed when the element goes out of scope. Suitable smart pointers are available in boost or C++11, or you could use std::auto_ptr<> but should carefully read about its semantics beforehand to see if it's suitable and how to safely use it.
Separately, if there's a Foo::operator=(Some_Type*) then you could set array[3] = NULL;, and it would do whatever that assignment operator did to array[3]. Still, if Foo is not a pointer, it is probably a bad idea for it to allow someone to assign NULL to it.

How could a pointer to a structure be an array?

This is really a noob quick question.
Imagine you have a struct called "No" and the following piece of code:
No *v_nos; // What does this mean?
Where I took this from they were calling "v_nos" a array? Isn't it simply a pointer to a struct "No"?
Thanks.
Arrays and pointers are NOT the same. In your case, the variable is a pointer, not an array. Even if they are not the same, the confusion is quite common and you will find in many places (including C/C++ books) that they are the same thing. This means that you should get acquainted to people calling pointers arrays.
When the C language was developed they decided that instead of passing arrays by value (possibly requiring a huge amount of copying and stack memory) they would convert silently the array into a pointer to the first element and then pass that pointer to the function.
void f( int a[3] ); // valid and misleading
// what it means:
// void f( int *a);
void test() {
int array[3];
f( array );
// what it means:
// f( & array[0] )
}
For backwards compatibility C++ keeps that feature around and you cannot pass arrays by value, nor define a function that takes an array by value (in both cases it will be converted to a pointer to the first element silently). At the same time, you can use the array access syntax on pointers to simplify pointer arithmetic, making it more confusing:
int array[3];
int *pointer = array; // simplified:
// int * pointer = & array[0]
pointer[2]; // equivalent to *(pointer+2) or array[2]
This means that with regular functions both in C and C++ arrays silently decay into pointers and most people will have the idea that they are the same thing: an array is a pointer to the first element. Well, they are not.
Both in C and C++ they are different entities, even if some usage patterns are equivalent due to that design decision. But they are in fact different:
int array[3]; sizeof(array); // 3*sizeof(int)
int *p1=array; // sizeof(int*), usually 4/8 bytes for 32/64 bit
int *p2=new int[3]; // sizeof(int*)
After passing through a function/method call, they are all pointers:
void f( int array[3] ) { sizeof(array); } // sizeof(int*) it is really a pointer! size is ignored
void g( int *p ) { sizeof(array); } // sizeof(int*)
In C++ things become even more interesting, as pass-by-value is not the only available paradigm and you can pass by reference:
void f( int (&array)[3] ); // funny syntax to pass an array of 3 integers by reference
void testf() {
int array1[3]; f(array1); // correct
int array2[2]; // f(array2); compilation error, it is not an array of 3 ints!
int *p = array1; // f(p); compilation error, it is not an array of 3 ints!
}
void g( int array[3] ); // means: void g( int *array );
void testg() {
int array1[3]; g(array1); // correct, the array decays into & array[0]
int array2[2]; g(array2); // correct, the array decays again
int *p = array1; g( p ); // correct it is a pointer
}
Note that when you define a function that takes an array by value you are actually defining a function that takes a pointer by value and that the compiler will not check that the argument to the function call actually has that size. This is a known source of errors and the reason why most functions that take arrays also take a size parameter.
Lastly, you cannot create arrays dynamically, you can only acquire memory dynamically into pointers, so when you need a heap allocated array you are actually in need of a pointer into a heap allocated contiguous block o memory:
void test() {
int *p = new int[3];
// int array[3] = new int[3]; // error!! an array is not a pointer
delete p;
}
At the end this all means that they are not the same thing, but that you can always use an array in the place of a pointer and it will be automatically converted by the compiler into a pointer to the first element of the array. More often than not, people will refer to pointers into a block of contiguously memory (whether stack or heap allocated) as array.
In terms of implementation, arrays and pointers are the same. That is, arrays are simply implemented as pointers to the first element in the array. The difference between
No *v_nos;
and
No v_nos[3];
Is that the latter sets aside memory for 3 elements for that array, while the pointer would need to have memory allocated using malloc (or new).
You could still treat the second one as the pointer that it is though, for example *v_nos would give you the first element, &v_nos would give the address of the pointer.
You are correct, but it can also be used as an array :
v_nos = new Nos[10];
v_nos[5].whatever = something;
// etc
Yes, it declares (but does not initialise) a pointer to a No.
Its a pointer to a No struct.
If they are calling it an array, that pointer could point to the first member of an array of No structs
for example
No* nos= getNosArray();//pseudocode
*nos;//first element
*(nos+1)//2nd element;
Arrays and pointers are more or less interchangeable in C++. You can dereference an offset from a pointer - *(v_nos+2) - and it's effectively the same as indexing an array v_nos[2]. In fact you can use either notation, IIRC. Under the covers both examples tell the compiler to do the same thing: increment the pointer by 2 * the size of the pointed-at object, and then return what it finds at that location.
typedef struct NO
{
int x;
}_NO;
int main()
{
_NO* v_nos;
_NO *v_nos_array;
v_nos = new _NO(); // allocate mem for 1 struct
v_nos_array = new _NO[100]; allocate mem for 100 structs
for(1=0; 1<100; i++) v_nos_array[i].x = i; //five some value to 'x' of each struct
for(1=0; 1<100; i++) cout << v_nos_array[i].x << "\n";
}
hope you can extract out the meaning. Note that an array with a single element is still an array.