How to store object pointers in an array - c++

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

Related

C++ reading and writing problems in using std::vector with classes

I have this class in a hpp file:
class info
{
public:
float lux[100];
float pwm[100];
float time[100];
float ref_lux;
int counter_samples_stream;
};
In the cpp file that contains this header, I create a vector of this class and because I put it in the beginning of the cpp file it is a global variable. This is the code I use to create it:
std::vector <info*> vect_node[3]; //creates 3 instances of class info in a vector
Inside the function(called abc) we are changing and initializing the vector's data by doing per example this: vect_node[1].lux[0] = 25; .
We are also trying to access the vector's data in another function(called zys) but when trying to access it the program crashes and returns core dumped.
Neither function abc or zys pass the vect_node in its arguments. The doubt is how can I write in vec_nodein a function in a way it changes its values permanently(and not only in the function) and read from this vector now updated in another function(syz).
The syntax std::vector<info*> vect_node[3]; will create an array of 3 std::vectors, in the same way that int my_array[3]; declares an array of 3 ints.
If you want to create a single std::vector with an initial capacity of 3, use the fill constructor. For example,
std::vector<info*> vect_node{3, nullptr};
will construct a std::vector called vect_node with an initial capacity of 3, where every element in the vector is of type info* has the initial value nullptr.
As pointed out in the comments, if you do not want a vector of pointers, you can instead use
std::vector<info> vect_node{3};
In this case, a std::vector of size 3 will be created called vect_node. Each element of the vector will contain an info object. Using this approach, your
vect_node[1].lux[0] = 25;
will now be valid.
Documentation for the std::vector constructors can be found here.
One way to easily initialise your vector of pointers is to use smart pointers so in one line you can do:
std::vector<std::shared_ptr<info>> vect_node(3, std::make_shared<info>());
Which will create a vector of three smart pointers and allocate the memory. You will then be able to just discard the vector without much worrying. You can modify elements with vect_node[O]->lux[0] = 10;
You just need to create a constructor for your class info.

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

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

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.

C++ - Define Vector size with class argument

Hello I'm trying to create a genetic algorithm with C++ and I tried to use vector as the container the problem is I didn't know how to set the size of the vector because the vector have a class argument like this
class population
{
friend class chromosome;
private:
int population_number;
int best_index[2];
vector <chromosome *> chromosome_population;
public:
population(int numberOfPopulation);
population(int numberOfPopulation,int numberOfSynapse);
~population();
int worst_chromosome();
void mating();
void crossover(int parent_1,int parent_2);
};
this is the population class and here's the chromosome class
class chromosome
{
friend class population;
private:
int chromosome_id;
float fitness;
vector <gen *> gen_chromosome;
public:
chromosome();
~chromosome();
void fitness_function();
void mutation_translocation();
int get_chromosome_size();
};
how can I set the vector length in the population class constructor? I've tried to use vector.pushback and vector.resize but both will give me error because the argument doesn't match. Actually I'm understand why it become error but I didn't know how to match the argument inside the vector pushback here's my population constructor
population::population(int numberOfPopulation)
{
srand (time(NULL));
population_number = numberOfPopulation;
for(int a=0;a<population_number;a++)
{
chromosome_population.push_back();
}
cout<<chromosome_population.size();
for(int i=0;i<population_number;i++)
{
chromosome_population[i]->chromosome_id = i;
int chromosome_length = rand() % 10 + 1;
for(int j=0;j<chromosome_length;j++)
{
chromosome_population[i]->gen_chromosome[j]->basa_biner = rand()%1;
chromosome_population[i]->fitness = (rand()%99)+1;
}
}
}
If is there any other information you want you can tell me in the comment and I'll add the information you needed. Thanks before.
std::vector has several constructors and one of the variants accepts the initial number of elements to be stored in the vector.
Specify the size of the vector in the population constructor's initializer list:
population::population(int numberOfPopulation) :
population_number(numberOfPopulation),
chromosome_population(numberOfPopulation)
{
}
Give this approach, the population_number member variable is unnecessary as it can be obtained by chromosome_population.size().
Specifying an initial size on the vector will mean that it contains numberOfPopulation null pointers. Before accessing elements in the vector you need to create objects, in this case using new. If the elements are copyable and polymorphic behaviour is not required then recommend using vector<chromosome> instead. If you must use dynamically allocated elements in the vector then you must allocate first:
chromosome_population[i] = new chromosome();
and remember to delete when no longer required.
It also desirable to use a form of smart pointer instead of raw pointers. An advantage of using the smart pointer is that when the vector<unique_ptr<chromosome>> goes out of scope the elements will be destructed for you, without having to explicitly call delete on each of the elements. See What C++ Smart Pointer Implementations are available? for a useful listing of the available smart pointers.
Note that vector::push_back() accepts an argument, with same type as its element. So the correct invocation of push_back() is:
chromosome_population.push_back(new chromosome());
If you specify an initial size of the vector at construction, calling push_back() will add elements after the initial (null pointers in this case) elements in the vector.

Adding element to Array of Objects in C++

How do I add an element to the end of an array dynamically in C++?
I'm accustomed to using vectors to dynamically add an element. However, vectors does not seem to want to handle an array of objects.
So, my main goal is having an array of objects and then being able to add an element to the end of the array to take another object.
EDIT**
Sorry, its the pushback() that causes me the problems.
class classex
{
private:
int i;
public:
classex() { }
void exmethod()
{
cin >> i;
}
};
void main()
{
vector <classex> vectorarray;
cout << vectorarray.size();
cout << vectorarray.push_back();
}
Now I know push_back must have an argument, but What argument?
Now I know push_back must have an argument, but What argument?
The argument is the thing that you want to append to the vector. What could be simpler or more expected?
BTW, you really, really, really do not want exmethod as an actual method of classex in 99% of cases. That's not how classes work. Gathering the information to create an instance is not part of the class's job. The class just creates the instance from that information.
Arrays are fixed sized containers. So enlarging them is not possible. You work around this and copy one array in a bigger and gain space behind the old end, but that's it.
You can create a array larger than you currently need it and remember which elements are empty. Of course they are never empty (they at least contain 0's), but that's a different story.
Like arrays, there are many containers, some are able to grow, like the stl containers: lists, vectors, deques, sets and so on.
add a Constructor to set i (just to give your example a real world touch) to your example classex, like this:
class classex {
public:
classex(int& v) : i(v) {}
private:
int i;
};
An example for a growing container looks like this:
vector <classex> c; // c for container
// c is empty now. c.size() == 0
c.push_back(classex(1));
c.push_back(classex(2));
c.push_back(classex(3));
// c.size() == 3
EDIT: The question was how to add an element to an array dynamically allocated, but the OP actually mean std::vector. Below the separator is my original answer.
std::vector<int> v;
v.push_back( 5 ); // 5 is added to the back of v.
You could always use C's realloc and free. EDIT: (Assuming your objects are PODs.)
When compared to the requirement of manually allocating, copying, and reallocating using new and delete, it's a wonder Stroustrup didn't add a keyword like renew.