Arrays and overwriting in C++ - can I reuse the same object? - c++

I'm making an array of vectors to save as normals. Because we haven't learned how to do vectors in class yet, I've made a struct which serves just as well:
struct vector3
{
double xcoord;
double ycoord;
double zcoord;
};
Then, at the beginning of my function, I have this:
vector3 vector;
vector3* normalField = new vector3[x];
While the function loops through, in each loop, it applies new values to "vector" - at the end of the function, it sets a part of the array to be vector.
normalField[x] = vector;
The idea is to save memory by not creating a whole bunch of new vectors, and because I have no clue when and where I would be able to use the delete function on that group of vectors. Will this work? Or not? What's the best way of doing this?
The code is very wordy as a whole - I'm writing an algorithm to create a field of normals for procedurally generated terrain. I don't use the built-in vector class because we're not supposed to for some stupid reason. I blame the professor.

The assignment normalField[x] = vector is going to deep copy the data in vector; you will be creating as many vectors as there are elements in normalField[].
Remember too that in C++ the only difference between a struct and a class is that in a struct data members and functions are public by default, but in a class they are private by default.

What you want can be implemented either via array, and creating a new, bigger array when your need for vectors is increased (essentially replicating the behaviour of std::vector), or by using a linked list, which could look like this:
struct vector3List {
vector3 v;
vector3List * next;
};
More refined solutions exist, of course, but the choice depends on what you need to do on the vectors.
In case you are not sure how a list is used, here is an example:
vector3List * listBegin = new vector3List();
// Setup your vector
listBegin->v.coordX = 6;
// Set the end of the list
listBegin->next = 0;
// You need one more vector
listBegin->next = new vector3List();
// Use some kind of helper pointer to keep track of what vector you are examining
// if you need it
vector3List * iterator = listBegin->next;
// Setup this new second vector
iterator->v.coordX = 5;
// Remember to set the end of the list!
iterator->next = 0;
// Iterate throgh the list
iterator = listBegin;
while ( iterator != 0 ) {
// Do stuff
iterator = iterator->next;
}
This is, of course, a naive implementation, but you get the idea.

Related

In C++, How do I store values into a vector that is inside of a vector when the two vectors are of different types?

I am writing a program where I need to use the following data structure:
struct shape
{
std::vector<float> verts; // contains the x & y values for each vertex
char type; // the type of shape being stored.
float shapeCol[3]; // stores the color of the shape being stored.
float shapeSize; // stores the size of the shape if it is a line or point
};
In my main program I need a vector of type shape. How would I store values into the vector inside of the struct shapes using the the vector of struct shapes.
For instance, vector<shape> myshapes;
If I wanted to store a value into the first index of my verts vector, inside of my first index of my myshapes vector how would I do this?
in pseudo code it would look something like this, with i being the index:
myshapes[i].vector[i] = 4; // but I know this is incorrect
Would this be easier to implement using a STL list instead and if so what would that syntax look like?
Thanks for the help I am new to vectors so any advice would be appreciated.
vector supports the use of the [] operator. The syntax and semantics are very similar to using the [] operator with arrays. See: http://en.cppreference.com/w/cpp/container/vector/operator_at.
As with any struct member, you need to access it by name. myshapes[i].verts[j] = 4;.
The general advice given is to use std::vector as your default container of choice. Naturally if you have specific needs (like adding/removing items in the middle of the container) other containers may have better performance characteristics.
If your vector(s) start out empty, you'll have to add elements to them before you can index into them with operator[]. This is usually done with push_back (to add an existing shape object) or emplace_back (to construct a new shape object directly in the vector).
Given vector<shape> myshapes, you could add some shapes like this:
// add 10 shapes
for (size_t n = 0; n < 10; n++) {
shape s; // creates a new, blank shape object
// initialize the shape's data
s.type = ...;
s.shapeSize = ...;
// etc.
// add verts
s.verts.push_back(1.0f);
s.verts.push_back(2.0f);
s.verts.push_back(3.0f);
// etc.
// add the shape to the vector
myshapes.push_back(std::move(s));
}
(Since we're done with s on that last line, we can use std::move. This allows push_back to move the shape's data into the vector instead of copying it. Look up move semantics for more info.)
Once you have stuff in the vector, you can access elements by index like this:
myshapes[index of shape].verts[index of vertex within that shape]
Using [] with an invalid index or when the vector is empty invokes undefined behavior (don't do it or your program will crash/malfunction).

How to store object pointers in an array

I'm fairly new to c++ and this problem's got me bad.
In my project I'm using SFML libraries to create asteroids. I declared a class named _asteroids and want to create a bunch of asteroid objects inside the class. Someone suggested I stored the objects inside an array. Later I learned that it wasn't possible to store objects inside an array, but you could store pointers to objects.
In summary I want to:
-Create objects inside the _asteroids class
-Store the pointers to those objects inside an array
-Be able to call those objects by their pointers from the array and change their values
How do I go about doing that? Here is some of my code to do with this:
class _asteroids{
float angle; //Angle
sf::Vector2f a_pos; //Position
sf::Vector2f a_vel; //Velocity
void makeAsteroids(int); //This generates the asteroid's appearance
bool Remove(); //If this is false the object is removed
public:
void Update(); //This updates the position
};
In C++ you should - if at all possible/reasonable - avoid (raw) pointers and C-style arrays. C++ provides standard containers. Like C-style arrays they can hold all kind of element types but they have some benefits that a C-style array doesn't. For instance most containers can grow/shrink when you need it - in other words, their size can adjust itself as you add or remove elements. On top of that, they have a number of member function that will allow you to operate on the contained elements in an easy way.
The vector container is very popular. In many aspects it is just like an array once the elements have been added, i.e. you access elements using var[i]. You can add elements to the end of the vector using push_back.
Example:
std::vector<_asteroids> allAsteroids;
allAsteroids.push_back(_asteroids()); // Add _asteroids object to end of vector
allAsteroids.push_back(_asteroids()); // Add _asteroids object to end of vector
allAsteroids.push_back(_asteroids()); // Add _asteroids object to end of vector
cout << allAsteroids.size() << endl; // Will print 3
for (auto& a : allAsteroids) // Iterate over all asteroids in the vector
{
a.Update(); // Call Update for current element
}
// The same as above in a different way
for (int i = 0; i < allAsteroids.size(); i++)
{
allAsteroids[i].Update(); // Call Update for i'th element
}
This was just a few examples of what you can do with vector. There are many more.
Check http://www.cplusplus.com/reference/vector/vector/ for more information - all member function of vector is shown to the left on that site.
Sure you can save Asteroid within an std::vector
class Asteroid {};
std::vector<Asteroid> asteroids;
Asteroid as1;
asteroids.push_back(as1);

C++ two arrays with some duplicate data

I'm working on N-body simulations in C++, I have collected all particles together using an array of a particle class. I need to work on sub-collections of particles separately, perhaps in a new array, but would still like to keep the full collection at the same time.
I already have code which takes an array of particles and acts on them, so ideally I'd like to just make new sub arrays pointing to the same data. Is there a good (neat, and efficient) way to define a sub-array pointing to the same memory as the main array of all the particles?
For example:
particle *full = new particle [10];
// define full here
particle *sub = // last 5 entries of full
func(full); // work on whole collection
func(sub); // work on sub collection
func(full); // work on whole collection with changes on sub[]
I found this post about working on sub arrays which isn't really what I want to do.
Any suggestions would be fantastic, this is my first large-ish project.
In C++ I'd use vectors instead of arrays (personal taste).
so
vector<particle> full;
//fill in `full`
vector<particle*> sub;
for(unsigned i=0;i<5;i++) if(full.size()>5-i) sub.push_back(&full[i]);
Now you have two vectors, sub's elements being pointers to full's elements
You may pass size to your method, and then:
particle *full = new particle [10];
// define full here
particle *sub = full + (10 - 5);// last 5 entries of full
func(full, 10); // work on whole collection
func(sub, 5); // work on sub collection
func(full, 10); // work on whole collection with changes on sub[]
delete[] full;
You can try using memcpy
void * memcpy ( void * destination, const void * source, size_t num );
Just pass the source arg as full+5, sizeof(particle) as size_t num and destination as the new pointer. From there they should be independent.
EDIT:
Use #Jarod42 approach if you want just a reference to the array instead of a whole copy

Container with non linear contents

I apologize if this question has been asked/answered elsewhere, but I didn't find anything since I'm not entirely sure what/how to ask this...
What I'm attempting to do is set up some kind of container; list, array, vector, what-ever, that will allow me to place and remove objects from specific indices.
Something like this:
[empty][empty][object][empty][object][object][empty]
I'm going to be moving objects from a vector into a specific index of this container and from this container to another vector.
What would be the best way to represent this and what kind of container would be best suited? I was originally using a vector, but the built in functions didn't seem to give me enough control over where the object ended up. It was either the front or the back.
I need to figure out the best way to hold those "empty" indices and move objects in and out of each element freely.
A simple, definitely sub-optimal, but quite effective solution could be to use a vector in the following way:
#include <iostream>
#include <vector>
using namespace std;
struct Your_Object
{
Your_Object& operator=(const Your_Object& other)
{
// Write a proper assignment operator here if you want to assign or swap values
cout << "hello from assignment operator"<<endl;
return *this;
}
};
int main() {
Your_Object nullObj;
std::vector<Your_Object> vec;
vec.reserve(10); // Creates 10 empty objects calling default constructors. Notice that this will NOT affect the vector's size, for that use resize()
Your_Object space5, space3; // Two objects to put in space5 and space3
// Put objects in space 5 and 3
vec[5] = space5;
vec[3] = space3;
// Move object in space 5 to another place
vec[1] = vec[5];
return 0;
}
http://ideone.com/YDu6LC
If you manage to write a proper copy-assignment operator (perhaps with move semantics if you're using C++11) which does a deep-copy of your object and if of course this proves to be not too burdensome for you, the above might be a simple working system for what you need to do.
Just remember to resize (or reserve, for the difference take a look here: https://stackoverflow.com/a/7397862/1938163) the space you need in advance.
If I understand your question correctly you want to place data in your vector according to a certain pattern.
You can use a simple vector and implement functions yourself to place your data.
For example if you want to place data in every third place :
void placeItem(std::vector<int> my_vector, int element, unsigned int index){
my_vector[((index+1)*3)-1]=element;
}
int retreiveItem(std::vector<int> my_vector, unsigned int index){
return my_vector[((index+1)*3)-1];
}
Then you can use placeItem and retreiveItem with indexes starting at 0.
If you simply meant that you want to place your data in arbitrary locations then you can use the [] syntax directly.

C++ class for arrays with arbitrary indices

Do any of the popular C++ libraries have a class (or classes) that allow the developer to use arrays with arbitrary indices without sacrificing speed ?
To give this question more concrete form, I would like the possibility to write code similar to the below:
//An array with indices in [-5,6)
ArbitraryIndicesArray<int> a = ArbitraryIndicesArray<int>(-5,6);
for(int index = -5;index < 6;++index)
{
a[index] = index;
}
Really you should be using a vector with an offset. Or even an array with an offset. The extra addition or subtraction isn't going to make any difference to the speed of execution of the program.
If you want something with the exact same speed as a default C array, you can apply the offset to the array pointer:
int* a = new int[10];
a = a + 5;
a[-1] = 1;
However, it is not recommended. If you really want to do that you should create a wrapper class with inline functions that hides the horrible code. You maintain the speed of the C code but end up with the ability to add more error checking.
As mentioned in the comments, after altering the array pointer, you cannot then delete using that pointer. You must reset it to the actual start of the array. The alternative is you always keep the pointer to the start but work with another modified pointer.
//resetting the array by adding the offset (of -5)
delete [] (a - 5);
A std::vector<int> would do the trick here.
Random acess to a single element in a vector is only O(1).
If you really need the custom indices you can make your own small class based on a vector to apply an ofset.
Use the map class from the STL:
std::map<int, int> a;
for( int index = -5; index < 6; ++index )
{
a[index] = index;
}
map is implemented internally as a sorted container, which uses a binary search to locate items.
[This is an old thread but for reference sake...]
Boost.MultiArray has an extents system for setting any index range.
The arrays in the ObjexxFCL library have full support for arbitrary index ranges.
These are both multi-dimensional array libraries. For the OP 1D array needs the std::vector wrapper above should suffice.
Answer edited because I'm not very smart.
Wrap an std::vector and an offset into a class and provide an operator[]:
template <class T>
class ArbVector
{
private:
int _offset;
std::vector<T> container;
public:
ArbVector(int offset) : _offset(offset) {}
T& operator[](int n) { return container[n + _offset] }
};
Not sure if this compiles, but you get the idea.
Do NOT derive from std::vector though, see comments.