initializing a vector of custom class in c++ - c++

Hey basically Im trying to store a "solution" and create a vector of these. The problem I'm having is with initialization. Heres my class for reference
class Solution
{
private:
// boost::thread m_Thread;
int itt_found;
int dim;
pfn_fitness f;
double value;
std::vector<double> x;
public:
Solution(size_t size, int funcNo) : itt_found(0), x(size, 0.0), value(0.0), dim(30), f(Eval_Functions[funcNo])
{
for (int i = 1; i < (int) size; i++) {
x[i] = ((double)rand()/((double)RAND_MAX))*maxs[funcNo];
}
}
Solution() : itt_found(0), x(31, 0.0), value(0.0), dim(30), f(Eval_Functions[1])
{
for (int i = 1; i < 31; i++) {
x[i] = ((double)rand()/((double)RAND_MAX))*maxs[1];
}
}
Solution operator= (Solution S)
{
x = S.GetX();
itt_found = S.GetIttFound();
dim = S.GetDim();
f = S.GetFunc();
value = S.GetValue();
return *this;
}
void start()
{
value = f (dim, x);
}
/* plus additional getter/setter methods*/
}
Solution S(30, 1) or Solution(2, 5) work and initalizes everything, but I need X of these solution objects. std::vector<Solution> Parents(X) will create X solutions with the default constructor and i want to construct using the (int, int) constructor. Is there any easy(one liner?) way to do this? Or would i have to do something like:
size_t numparents = 10;
vector<Solution> Parents;
Parents.reserve(numparents);
for (int i = 0; i<(int)numparents; i++) {
Solution S(31, 0);
Parents.push_back(S);
}

the example I gave as a comment uses copy constructor to create new objects.
You can do the following:
// override copy constructor
Solution(const Solution &solution) {
... copy from another solution
}
however be careful, as you no longer going to have exact object copy/construct if you introduce random generation in your copy constructor, i.e. Solution y = x; y != x
your best solution is something like you already have in my opinion

I have used the Boost assignment library for tasks like this. You may find it useful....

Related

Creating multiple objects and passing parameters through constructor

I am trying to understand how to create multiple objects(20 in the current case) and pass parameter to the constructor as shown in the comments of the code. Unfortunately, I cannot pass parameters as well as have an array of objects at the same time.
I tried this as well to create the object convector con(100,200, construct(20)); but it didn't seem to give the desired result
#include <iostream>
class construct {
public:
int a, b;
// Default Constructor
construct(int x1,int x2)
{
a = x1;
b = x2;
}
int getX1(){
return a;
}
int getX2(){
return b;
}
};
int main(){
int p,q;
construct* con = new construct[20](100,200);
for (unsigned int i = 0; i < 20; i++) {
p=con[i]->getX1();
q=con[i]->getX2();
printf("%d %d \n",p,q);
}
delete con;
return 1;
}
Expected result would be 20 objects created.
Just use std::vector. Seriously, there's no reason not to.
std::vector<construct> con(20, {100, 200});
Yeah, for this you are likely to need placement new sadly (or use std::vector, and pass a newly constructed object as the second argument).
// call global new (effectively malloc, and will leave objects uninitialised)
construct* con = (construct*)::operator new (sizeof(construct) * 20);
// now call the ctor on each element using placement new
for(int i = 0; i < 20; ++i)
new (con + i) construct(100, 200);

Write a function that may return either one or more values

Suppose I want to write a function that, say, returns the sum of f(x) for x in a certain range.
double func() {
double sum = 0.;
for (int i=0; i<100; i++) {
sum += f(i);
}
return sum;
}
But sometimes, in addition to the final sum I also need the partial terms, so I can do
pair<vector<double>,double> func_terms() {
double sum = 0.;
vector<double> terms(100);
for (int i=0; i<100; i++) {
terms[i] = f(i);
sum += terms[i];
}
return {terms, sum};
}
The thing is, this is code duplication. This seems very harmless in this example, but suppose the function is much larger (which it is in the situation that prompted me to ask this), and the two versions differ in just a handful of lines lines (in this example the logic is the same only the latter version stores the term in a vector before adding to sum, and returns a pair with that vector; any other logic is equivalent). Then I will have to write and maintain two nearly-identical versions of the same function, differing only in a couple lines and in the return statement. My question is if there is an idiom/pattern/best practice to deal with this kind of problem. Something that would let me share the common code between the two versions.
In short: I can write two functions and have to maintain two nearly-identical versions. Or I can just use the latter but that will be very wasteful whenever I just need the sum, which is unacceptable. What's the best pattern to deal with this?
I reckon that with C++17 one can do something like
template<bool partials>
double func(vector<double>* terms=nullptr) {
double sum = 0.;
if constexpr (partials)
*terms = vector<double>(100);
for (int i=0; i<100; i++) {
if constexpr (partials) {
(*terms)[i] = f(i);
sum += (*terms)[i];
} else {
sum += f(i);
}
}
return sum;
}
Which comes very close to what I intended, apart from using pointers (I can't use references because terms may be empty).
Your question title says "Write a function that may return either one or more values", but it's more than that; as your example shows, the function may also do a lot of different things long before a result is returned. There really is no general solution to such a broad problem.
However, for the specific case you've explained I'd like to offer a low-tech solution. You could simply implement both functions in terms of a third function and give that third function a parameter to determine whether the extra functionality is performed or not.
Here is a C++17 example, in which that third function is called func_impl and more or less hidden inside a namespace to make life easier for the client of func and func_terms:
namespace detail {
enum class FuncOption {
WithTerms,
WithoutTerms
};
std::tuple<std::vector<double>, double> func_impl(FuncOption option) {
auto const withTerms = option == FuncOption::WithTerms;
double sum = 0.;
std::vector<double> terms(withTerms ? 100 : 0);
for (int i = 0; i < 100; ++i) {
auto const result = f(i);
if (withTerms) {
terms[i] = result;
}
sum += result;
}
return std::make_tuple(terms, sum);
}
}
double func() {
using namespace detail;
return std::get<double>(func_impl(FuncOption::WithTerms));
}
std::tuple<std::vector<double>, double> func_terms() {
using namespace detail;
return func_impl(FuncOption::WithoutTerms);
}
Whether that's too low-tech is up to you and depends on your exact problem.
Here was a solution that suggested to pass an optional pointer to vector and to fill it only if present. I deleted it as other answers mention it as well and as the latter solution looks much more elegant.
You can abstract your calculation to iterators, so callers remain very simple and no code is copied:
auto make_transform_counting_iterator(int i) {
return boost::make_transform_iterator(
boost::make_counting_iterator(i),
f);
}
auto my_begin() {
return make_transform_counting_iterator(0);
}
auto my_end() {
return make_transform_counting_iterator(100);
}
double only_sum() {
return std::accumulate(my_begin(), my_end(), 0.0);
}
std::vector<double> fill_terms() {
std::vector<double> result;
std::copy(my_begin(), my_end(), std::back_inserter(result));
return result;
}
One of the simple way is to write a common function and use input parameter to do condition. Like this:
double logic(vector<double>* terms) {
double sum = 0.;
for (int i=0; i<100; i++) {
if (terms != NULL) {
terms.push_back(i);
}
sum += terms[i];
}
return sum;
}
double func() {
return logic(NULL);
}
pair<vector<double>,double> func_terms() {
vector<double> terms;
double sum = logic(&ret);
return {terms, sum};
}
this method is used in many conditions. The Logic can be very complicated and with many input options. You can use the same logic through different parameters.
But in most cases, We need not that much return values but just different input parameter.
If you are not for:
std::pair<std::vector<double>, double> func_terms() {
std::vector<double> terms(100);
for (int i = 0; i != 100; ++i) {
terms[i] = f(i);
}
return {terms, std::accumulate(terms.begin(), terms.end(), 0.)};
}
then maybe:
template <typename Accumulator>
Accumulator& func_helper(Accumulator& acc) {
for (int i=0; i<100; i++) {
acc(f(i));
}
return acc;
}
double func()
{
double sum = 0;
func_helper([&sum](double d) { sum += d; });
return sum;
}
std::pair<std::vector<double>, double> func_terms() {
double sum = 0.;
std::vector<double> terms;
func_helper([&](double d) {
sum += d;
terms.push_back(d);
});
return {terms, sum};
}
The simplest solution for this situation I think would be something like this:
double f(int x) { return x * x; }
auto terms(int count) {
auto res = vector<double>{};
generate_n(back_inserter(res), count, [i=0]() mutable {return f(i++);});
return res;
}
auto func_terms(int count) {
const auto ts = terms(count);
return make_pair(ts, accumulate(begin(ts), end(ts), 0.0));
}
auto func(int count) {
return func_terms(count).second;
}
Live version.
But this approach gives func() different performance characteristics to your original version. There are ways around this with the current STL but this highlights an area where the STL is not ideal for composability. The Ranges v3 library offers a better approach to composing algorithms for this type of problem and is in the process of standardization for a future version of C++.
In general there is often a tradeoff between composability / reuse and optimal performance. At its best C++ lets us have our cake and eat it too but this is an example where there is work underway to give standard C++ better approaches to handle this sort of situation.
I worked out an OOP solution, where a base class always compute sum and makes the current term available to derived classes, this way:
class Func
{
public:
Func() { sum = 0.; }
void func()
{
for (int i=0; i<100; i++)
{
double term = f(i);
sum += term;
useCurrentTerm(term);
}
}
double getSum() const { return sum; }
protected:
virtual void useCurrentTerm(double) {} //do nothing
private:
double f(double d){ return d * 42;}
double sum;
};
So a derived class can implement the virtual method and espose extra properties (other than sum):
class FuncWithTerms : public Func
{
public:
FuncWithTerms() { terms.reserve(100); }
std::vector<double> getTerms() const { return terms; }
protected:
void useCurrentTerm(double t) { terms.push_back(t); }
private:
std::vector<double> terms;
};
If one doesn't want to expose these classes, could fall back to functions and use them as a façade (yet two functions, but very manageable, now):
double sum_only_func()
{
Func f;
f.func();
return f.getSum();
}
std::pair<std::vector<double>, double> with_terms_func()
{
FuncWithTerms fwt;
fwt.func();
return { fwt.getTerms(), fwt.getSum() };
}

C++ Class/Function interaction

I'm fairly new to c++ classes and exactly how they work, but I'm trying to figure what issues I have with this code. What I'm trying to do is that the class handle the dice object, how many faces the die has and the value of the roll. Then use those values later on in the code. I know I've done something fundamentally wrong here I'm just not sure what.
The class header is:
class Dice {
private :
int face ;
int value ;
public:
Dice()
{
face = 6;
}
Dice(int faceVal)
{
face = faceVal;
}
Dice(Dice &other)
{
face = other.face;
}
Dice& operator=(const Dice &rhs);
int roll() ;
int getValue() const { return value; }
int getFace() const { return face; }
} ;
Dice& Dice::operator=(const Dice &rhs)
{
face = rhs.face;
return *this;
}
#endif
The functions/methods that are being used:
int Dice::roll()
{
srand((unsigned)time(0));
int randomNumber = 1 + rand() % 5;
value = randomNumber;
return randomNumber;
}
int rollAll(Dice cup[], int n)
{
int faces = 0;
for(int i = 0; i < n; i++)
faces += cup[i].roll();
return sum ;
}
And the entrance into them from the main function is:
total = rollAll(cup,2) ;
for (int i = 0 ; i < 2 ; i++ )
(arr[i] = cup[i].getValue());
The glaring issue with your code is that your copy constructor and assignment operator are incorrect. You are failing to actually copy the object fully, as you are missing the value member in the copying operations.
Dice(Dice &other)
{
face = other.face;
// where is the `value` member?
}
So where is the copy of the value member being made? If you miss any members during the copy, your program will be using "half-copies" masquerading as real copies. These types of bugs, where you don't copy everything, are some of the toughest to find.
This is one reason why you should not get involved in writing copy/assignment functions unless it is absolutely required. In your case, the compiler generated copy constructor / assignment operator will do the job correctly without you having to write one.

Why does this code generate error?

I have a class that contains an array of another class called Sphere. Right now i am not sure why one part of code is generating an error.
.H file
sphere* list;
int listlen;
void add(sphere x);
sarray operator +(const sarray& arrayone);
.Cpp
sarray::sarray()
{
listlen = 0;
list = new sphere[200000];
}
sarray::~sarray()
{
delete [] this->list;
}
void sarray::add(sphere x) // Function for adding spheres to the list.
{
listlen++;
list[listlen-1] = x;
}
void sarray::operator = (const sarray& arrayone)
{
this -> list = NULL;
for(int i = 0; i < arrayone.listlen; i++)
{
this -> add(arrayone.list[i]);
}
}
sarray sarray::operator +(const sarray& arrayone)
{
sarray temparray;
for(int i = 0; i < arrayone.listlen; i++) // add all the elements from the first array to the temporary one
{
//sphere temp = arrayone.list[i];
temparray.add(arrayone.list[i]);
}
for(int j = 0; j < this -> listlen; j++)// add all the elements from the second array to the temporary one
{
temparray.add(list[j]);
}
return temparray;
}
The sphere class got a member variable called "Radius"
which when i try to compare like this
float a = 10;
for(int i=0; i > this->listlen;i++)
if(this->list[i].Radius > a) //<-- Can read the values
Works fine, but when change this part of the code
float a = 10;
sarray temparray = arrayone + *this;
for(int i = 0; i < temparray.listlen; i++)
if(temparray.list[i].radius > a) // Error comes here!
"Unhandled exception at 0x00138503: Access violation reading location"
while this doesent. I guess the problem is in the Add/operator function but i cant find it.
The following part looks problematic:
void sarray::add(sphere x) // Function for adding spheres to the list.
{
list[listlen-1] = x;
}
you should rather have something like this
void sarray::add(sphere x) // Function for adding spheres to the list.
{
list[listlen++] = x;
}
Also you should better have some error checking in add method.
OK, having looked at the destructor, you have a pointer to sphere in your sarray and has a destructor to destroy the pointer. This is all good except you haven't defined your own copy constructor which means the default copy constructor is used. In the function operator+ where you return temparray, a copy of the local copy is returned. The default copy constructor is called to create the copy. Then the local one will be destructed. Now the returned sarray copy's list will point to invalid data. You need to define your own copy constructor to make a deep copy of the list pointer.

Dynamically allocating array of objects

I need a double pointer of type DizzyCreature (my class) to point to an array of DizzyCreature pointers. When I run it I get "Access violation reading location 0x...". I can make a DizzyCreature* and call its member functions just fine, but when cannot run through the array and do the same thing for each obj.
I am following these instructions:
http://www.cplusplus.com/forum/beginner/10377/
Code
Server.h:
class Server
{
public:
Server(int x, int y, int count);
~Server(void);
void tick();
private:
DizzyCreature** dcArrPtr;
DizzyCreature* dcPtr;
int _count;
};
Server.cpp:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count]; // this works just fine
dcArrPtr = new DizzyCreature*[count]; // this doesn't (but gets past this line)
_count = count;
}
Server::~Server(void)
{
delete[] *dcArrPtr;
delete[] dcPtr;
}
void Server::tick()
{
dcPtr->takeTurn(); // just fine
for (int i = 0; i < _count; i++) {
dcArrPtr[i]->takeTurn(); // crash and burn
}
}
EDIT:
The member function takeTurn() is in a parent class of DizzyCreature. The program makes it into the function, but as soon as it attempts to change a private member variable the exception is thrown. If it matters, DizzyCreature is of type GameCreature and WhirlyB as this is an assignment on MI.
You have allocated space for dcArrPtr, but didn't allocate every object in this array. You must do following:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count];
dcArrPtr = new DizzyCreature*[count];
for ( int i = 0; i < count; i++ ) {
dcArrPtr[ i ] = new DizzyCreature;
}
_count = count;
}
Server::~Server(void)
{
for ( int i = 0; i < count; i++ ) {
delete dcArrPtr[ i ];
}
delete[] *dcArrPtr;
delete[] dcPtr;
}
This:
dcPtr = new DizzyCreature[count];
"creates" an array of DizzyCreatures, whereas:
dcArrPtr = new DizzyCreature*[count];
"creates" an array of pointers to DizzyCreatures, but crucially doesn't create instances for those pointers to point to.
The preferred solution is to use a standard container for tasks like this anyway though. If you really want to do it like this (and are aware that it's not best practice to do this manually) then you'll need a loop to call new for eachelement in the array of pointers.
You allocate an array of count pointers instead of an array of count objects.
Instead of
dcArrPtr = new DizzyCreature*[count];
you might want to
dcArrPtr = new DizzyCreature[count];
You're allocating an array of pointers, but those pointers aren't valid until you set them to something.
double **arr = new double*[10];
for(int i=0;i<10;++i) {
arr[i] = new double[10];
}
That said, when starting out with C++ you should probably avoid raw arrays and instead use std::array and std::vector:
class Server
{
public:
Server(int x, int y, int count);
void tick();
private:
std::vector<std::vector<DizzyCreature>> dcArrPtr;
std::vector<DizzyCreature> dcPtr;
};
Server::Server(int x, int y, int count)
{
dcPtr.resize(count);
dcArrPtr.resize(count);
}
void Server::tick()
{
dcPtr[0].takeTurn();
for (int i = 0; i < dcArrPtr.size(); i++) {
dcArrPtr[i][0].takeTurn();
}
}
Use a
std::vector<std::vector<DizzyCreature>>
Furthermore, if you want to use raw pointers (which I do not recommend), you'll have to allocate memory for each pointer in your array.
class A
{
std::vector<std::vector<int>> v_;
public:
A()
: v_(500, std::vector<int>(500))
{} // 500 x 500
};
class B
{
int** v_;
public:
B()
: v_(new int*[500])
{ // not even exception safe
for (int i = 500; i--; )
v_[i] = new int[500];
}
~B()
{
for (int i = 500; i--; )
delete[] v_[i];
delete[] v_;
}
};
If you would have seen the implementation of dynamic memory allocation of 2-Dimensional array . That would have given you a better insight of how to proceed in such cases . Most of the answers has already answered you what to do . But just go through any link and see how is memory allocated in case of 2-D array . That Will also help you .