array of objects where constructor has an argument - c++

I want to have an array of objects.
Each object has a constructor with one argument.
My object array initialisation :
set s[]=new set[n]; // creates an array of n objects of class set
However, it says that I cannot do so, because my constructor requires an argument.
My Constructor:
set(int size){}
I've understood the problem, but cant think of a good solution.
What I can do, is either initialise each object seperately :
set s1(size);
set s2(size); //& so on.....
or remove the argument from constructor......both solutions are not quite satisfactory
Can anyone help me out to find a better solution to this ?
Note: 'size' value of each object is different/dynamic

#include <vector>
...
std::vector<set> s(n, set(x,y,z));
This will create a vector (a dynamically resizeable array) of n set objects, each a copy of set(x,y,z). If you want to use different constructors for various elements, or the same constructor with different arguments:
std::vector<set> s; // create empty vector
s.push_back(set(x,y,z));
s.push_back(set(y,z,x));
...
... // repeat until s.size() == n

You can make a different constructor that takes no arguments and initializes the values, and then set the values of each variable in a loop
set() {
this.size = 0;
}
and then in a for loop initialize each element with the desired size, using direct binding or a getter/setter functions.
for(int i = 0; i < n; i++) {
s[i].size = value[i]; // or create a setter function
}

Related

std::vector saving only last one element pushed

I have created 2 classes, algorithm and peopleEncoding:
peopleEncoding has a private attribute _solution which is a std::vector containing integers.
algorithm has a private attribute _population which is a std::vector containing pointers to solutionEncoding instances.
The algorithm class also has a method called initPopulation which fills _population like this:
void initPopulation (unsigned peopleQuantity){
solutionEncoding * newOne = new solutionEncoding();
for (unsigned i = 0; i < peopleQuantity; i++ ){
newOne->generateRandom();
this->_population.push_back(newOne);
}
}
If I print _solution attribute from peopleEncoding instances stored at _population (just after the push_back line) I get the expected results but if I do it after the loop encloser bracket the vector changes (they all are the same, equal to the last one pushed).
I´m not sure about the correct use of new.
The problem
This line:
this->_population.push_back(newOne);
pushes back at the end of the _population vector a pointer newOne that points to a solutionEnconding. Since you initialize this pointer only one, it's the same pointer to the same object that is used in all the items of the _population vector.
The expectations
When you call this member function:
newOne->generateRandom();
you probably change some attributes of your solutionEncoding object, and you seem to expect that every element of the _population vector is therefore random. But this is not the case, since you have only one object.
Potential solutions
To achieve what you want, you'd need to generate a new pointer to a different object in each iteration. Just move the line with the new into the loop. But this would not be a good approach, since you would have to do a lot of memory management (for every new, you'd need a delete) with some risks (e.g. shallow copy and double deletes).
A safer approach would therefore be to make _population a vector containing solutionEncoding objects. newOne would also be a solutionEncoding object: push_back() would store a different copy each time:
std::vector<solutionEncoding> _population;
...
void initPopulation (unsigned peopleQuantity){
solutionEncoding newOne{}; // create a new local object - no 'new' needed
for (unsigned i = 0; i < peopleQuantity; i++ ){
newOne.generateRandom(); // shuffle all this data :-)
_population.push_back(newOne); // store a copy of the current data
}
}
Now this works well if solutionEncoding is not a polymorphic class. If you'd intend to derive the solutionEncoding class in the future, this would not work because of slicing. In this case, you'd use a shared_ptr:
std::vector<shared_ptr<solutionEncoding>> _population;
...
void initPopulation (unsigned peopleQuantity){
for (unsigned i = 0; i < peopleQuantity; i++ ){
auto newOne = make_shared<solutionEncoding>(); // create a different new object each time
newOne->generateRandom(); // shuffle all this data :-)
_population.push_back(newOne); // store the pointer to the new object
}
}

Initialize vector passed by reference

I have a class Pixel and a class Image with a function used to update a pixel line. I want to initialize the pixel line. My problem is to initialize the vector. Actually I have this :
bool UpdateLine(std::vector<Pixel>& line, int nb)
{
bool noError = true;
line = new std::vector<Pixel>(nb);
// Do some stuff
return noError;
}
When I try this I have :
no viable overloaded '='
How can I initialize the vector ?
The expression you are using:
new std::vector<Pixel>(nb)
returns a pointer to std::vector<Pixel> (i.e.: std::vector<Pixel> *), and not a std::vector<Pixel>, which is what you need.
A distinction between initialization and assignment has to be done: you are assigning to line and not initializing it.
You can create a new vector and assign it to line by means of an assignment operator:
line = std::vector<Pixel>(nb);
What you do is assignment, not initialization.
Initializing a vector could be done like this:
std::vector<int> second (4,100); // four ints with value 100
In your case however, the vector is already declared outside of the function, so in that case you use vector::resize and do this:
line.resize(nb); // creates 'nb' objects 'Pixel'
PS: You don't need new keyword, except if you dynamically allocating memory for your vector.

C++ Class Variables: Initialization vs. Assignment and Initialization of vectors

I am working on a C++ program that has a series of class variables that contain vectors on some or all of the member variables. My question is three-fold:
Is it straight-forward to use constructors to initialize vector variables that are part of a class (see sample class definition below)? Could someone post an example constructor for the class below (or for at least the single and two-dimension vector variables)?
Is there a problem with simply initializing the variables myself in my code (i.e., iterating through each element of the vectors using loops to assign an initial value)?
Along the same lines, if the variables need to be initialized to different values in different contexts (e.g., zero in one instance, some number in another instance), is there a way to handle that through constructors?
Sample class definition:
class CreditBasedPoolLevel {
public:
int NumofLoans;
int NumofPaths;
int NumofPeriods;
double TotalPoolBal;
vector<int> NumofModeled;
vector<double> ForbearanceAmt;
vector<double> TotalAmtModeled;
vector<vector<int>> DefCountPoolVector;
vector<vector<double>> TermDefBalPoolVector;
vector<vector<double>> BalloonDefBalPoolVector;
vector<vector<double>> TermDefBalPoolVectorCum;
vector<vector<double>> TermSeverityAmt;
vector<vector<double>> TermELAmtPoolVector;
vector<vector<double>> BalloonELAmtPoolVector;
vector<vector<double>> TermELAmtPoolVectorCum;
};
In C++, initializing a variable calls its constructor. In a vector's case, this means it creates an instance of a vector with whatever the initial capacity is (10 I believe), with no values. At this point, you need to use push_back in order to fill the vector - even though it has a capacity, it will cause undefined behavior if you try to access unfilled areas directly (such as with NumofModeled[0]). You can also initialize it with some amount of space by using vector NumofModeled(x) (x being the number of spaces), but generally because vectors have dynamic size, it's easier to use push_back unless there is some reason you need to enter your data out of order.
Relates to the capacity part of one, if you try to access unfilled space in a vector you will get undefined behavior. It's pretty standard practice to fill a vector with a loop though, such as:
vector<int> v;
int in = 0;
while (cin)
{
cin >> in;
v.push_back(in);
}
Yes, but remember that like functions, constructors only differentiate by the type of input parameters. So, for example, you could have CreditBasedPoolLevel(int level) and CreditBasedPoolLevel(vector<int> levels), but not another with the definition CreditBasedPoolLevel(int otherint), because it would conflict with the first. If you want to be able to take different contextual input of the same type, you can use another variable to define the constructor type, such as CreditBasedPoolLevel(int input, string type) and use a switch block to define the initialization logic based on the type.
As for question number three, simply add a constructor with an argument that is the value you want to initialize the vectors with.
And if you just want the vectors to be default constructed, then there's nothing that needs to be done.
Constructor may look something like this:
CreditBasedPoolLevel::CreditBasedPoolLevel()
{
const int numDefCountPools = 13;
const int numDefCountPoolEntries = 25;
for(int i = 0; i < numDefCountPools; i++)
{
vector<int> v;
for(int j = 0; j < numDefCountPoolEntries; j++)
{
v.push_back(j + i * 5); // Don't know what value you ACTUALLY want to fill here
}
DefCountPoolVector.push_back(v);
}
}
Note that this is ONE solution, it really depends on what values you want, how you went them organized, etc, what is the "right" solution for your case.

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.

Using a constructor for an array of structures

I want to create an array of structures. The structure uses a constructor as shown below:
struct struct_seedinfo {
struct_seedinfo(const mxArray *prhs[ ],const int seed_id){
mxArray *mat_coords, *mat_defvectorinit, *mat_corrcoef, *mat_roi_id;
mat_coords = mxGetField(prhs[1],seed_id,"coords");
coords = mxGetPr(mat_coords);
mat_defvectorinit = mxGetField(prhs[1],seed_id,"defvectorinit");
defvectorinit = mxGetPr(mat_defvectorinit);
mat_corrcoef = mxGetField(prhs[1],seed_id,"corrcoef");
corrcoef = *(mxGetPr(mat_corrcoef));
mat_roi_id = mxGetField(prhs[1],seed_id,"roi_id");
roi_id = *(mxGetPr(mat_roi_id));
}
double *coords;
double *defvectorinit;
double corrcoef;
double roi_id;
static int num_seeds;
};
How could I create an arbitrary sized array of this structure? I need to allocate memory for it, but it seems like I would need to allocate memory without calling the constructor, and then call the constructor later in a forloop. Is there a good or preferred way of doing this? Thanks.
You can do std::vector<struct_seedinfo>. This will create an array and it will automagically increase in size when needed.
You'll also need to overload the copy constructor and copy-assignment operator for your struct to be able to be used in a vector. You need a destructor too. This is called the Rule of Three in C++
Well since the size stay constant, you can use the following solution :
*This assumes your ok with defining a default constructor.
First declare a default constructor in your class.
struct_seedinfo(){
//If you want to initlaize something.
}
Than you can use the following to create you array :
struct_seedinfo * arr = new struct_seedinfo[size_of_array];
And then you need for each space to do your specific build :
arr[i] = struct_seedinfo(//arguments);
This is if you badly need an array, i do also think the vector solution is better.