'this' cannot be used in a constant expression error - c++

The error is on line 76 int res[mSize]; the problem is on mSize. It seems like a simple fix but I can't figure it out. If someone can figure it out or point me in the right direction that would be greatly appreciated.
Also, the deconstructor ~MyContainer(), I am not sure if I am using it right or if there is a correct place to put it.
Here is my code:
#include <iostream>
using namespace std;
class MyContainer
{
private:
int* mHead; // head of the member array
int mSize; // size of the member array
public:
MyContainer();
MyContainer(int*, int);
//~MyContainer();
void Add(int);
void Delete(int);
int GetSize();
void DisplayAll();
int FindMissing();
~MyContainer() {}
};
MyContainer::MyContainer()
{
mHead = NULL;
mSize = 0;
}
MyContainer::MyContainer(int* a, int b)
{
mHead = a;
mSize = b;
}
void MyContainer::Add(int a)
{
*(mHead + mSize) = a;
mSize++;
}
void MyContainer::Delete(int a)
{
int index;
for (int i = 0; i < mSize; i++)
{
if (*(mHead + i) == a)
{
index = i;
break;
}
}
for (int i = index; i < mSize; i++)
{
*(mHead + i) = *(mHead + i + 1);
}
mSize--;
}
int MyContainer::GetSize()
{
return mSize;
}
void MyContainer::DisplayAll()
{
cout << "\n";
for (int i = 0; i < mSize; i++)
{
cout << *(mHead + i) << " ";
}
}
int MyContainer::FindMissing()
{
int res[mSize];
int temp;
int flag = 0;
for (int i = 1; i <= mSize; i++)
{
flag = 0;
for (int j = 0; j < mSize; j++)
{
if (*(mHead + j) == i)
{
flag = 1;
break;
}
}
if (flag == 0)
{
temp = i;
break;
}
}
return temp;
}
int main()
{
const int cSize = 5;
int lArray[cSize] = { 2, 3, 7, 6, 8 };
MyContainer lContainer(lArray, cSize);
lContainer.DisplayAll();
lContainer.Delete(7);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl; lContainer.Add(-1);
lContainer.Add(-10);
lContainer.Add(15);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl;
cout << "First missing positive is: " << lContainer.FindMissing() << endl;
system("PAUSE"); return 0;
}

int res[mSize];
The size of the array mSize must be known at compile time. You cannot use a variable here. An option may be to define a macro with an largish value that will not exceeded.
static const int kLargeSize =100;
int res[kLargeSize];
Edited in response to the comments - const and constexpr are a better option than a macro.
Or even better, you can use std::vector - https://en.cppreference.com/w/cpp/container/vector

Related

Copying data in a simple vector class

I'm trying write my own vector class:
template <typename T>
class Vector {
public:
Vector(int default_size = 2) :
size(0), data_member(new T[default_size]), capacity(default_size) {};
Vector(const Vector& obj)
{
data_member = new T[obj.size];
data_member = obj.data_member;
size = obj.size;
capacity = obj.capacity;
}
void push_back(T& elem)
{
if (size == capacity)
resize(2 * size);
data_member[size] = elem;
size++;
}
void push_front(T& data)
{
if (size + 1 == capacity)
resize(2 * size);
for (int i = size - 1; i >= 0; i--)
{
data_member[i + 1] = data_member[i];
}
data_member[0] = data;
size++;
}
void pop_back()
{
--size;
}
void resize(int size_)
{
if (size_ > capacity)
{
T* temp = new T[size_];
memcpy(temp, data_member, size * sizeof(T));
delete[] data_member;
data_member = new T[size_];
data_member = temp;
//delete[] temp;
capacity = size_;
}
}
int get_size() { return size; }
T* getarr() { return data_member; }
private:
T* data_member;
int size;
int capacity;
};
and here is a main for testing my class
int main()
{
Vector<int> myint;
int a = 5, b = 8, c = 9;
myint.push_back(a);
myint.push_back(b);
myint.push_back(c);
Vector<int> you = myint;
int* arr1 = you.getarr();
for (int i = 0; i < you.get_size(); i++)
{
cout << *arr1 << endl;
arr1++;
}
cout << endl << endl;
int h[3] = { 1,2,3 };
int* hp = h;
int g[3] = { 4,5,6 };
int* gp = g;
int f[3] = { 4,5,6 };
int* fp = f;
Vector<int*> myarrint;
myarrint.push_back(hp);
myarrint.push_back(gp);
myarrint.push_back(fp);
int** arr = myarrint.getarr();
for (int i = 0; i < myarrint.get_size(); i++)
{
for (int j = 0; j < 3; j++)
{
cout << **arr << endl;
(*arr)++;
}
arr++;
}
cout << endl << endl;
Vector<string> mystr;
string s1 = "I";
string s2 = "went";
string s3 = "shopping";
mystr.push_back(s1);
mystr.push_back(s2);
mystr.push_back(s3);
string* str1 = mystr.getarr();
for (int i = 0; i < mystr.get_size(); i++)
{
cout << *str1 << endl;
str1++;
}
cout << endl << endl;
string i = "wow";
mystr.push_front(i);
string* str2 = mystr.getarr();
for (int i = 0; i < mystr.get_size(); i++)
{
cout << *str2 << endl;
str2++;
}
cout << endl << endl;
return 0;
}
I'm new in c++ and I'm really confused, I think in my push_back function, I'm just making my objects point to temp and I'm not copying temp in them , so if I want to delete temp in the end of my push_back function my data_members will be lost. So what is the right way to do so?
second if I want to make a dynamic array of strings my program will crash sometimes, and I think ,it's because of memcpy() in my resize function, still I don't know what should I do instead of it?

Arrays aren't behaving as I'm expecting

Pointers are still a little confusing to me. I want the split function to copy negative elements of an array into a new array, and positive elements to be copied into another new array. A different function prints the variables. I've included that function but I don't think it is the problem. When the arrays are printed, all elements are 0:
Enter number of elements: 5
Enter list:1 -1 2 -2 3
Negative elements:
0 0
Non-Negative elements:
0 0 0
I assume that the problem is that in the split function below i need to pass the parameters differently. I've tried using '*' and '**' (no quotes) for passing the parameters but I get error messages, I may have done so incorrectly.
void split(int alpha[], int bravo[], int charlie[], int aSize, int bSize, int cSize) {
int a = 0;
int b = 0;
for (int i = 0; i < aSize; ++i) {
if (alpha[i] < 0) {
alpha[i] = bravo[a];
++a;
}
else {
alpha[i] = charlie[b];
++b;
}
}
if (a + b != aSize) {
cout << "SOMETHING HAS GONE HORRIBLY WRONG!";
exit(0);
}
}
my main function (all arrays are required to be pointers):
int num_elements;
cin >> num_elements;
int * arr1 = new int[num_elements];
int x;
cout << "Enter list:";
for (int i = 0; i < num_elements; ++i) {
cin >> x;
arr1[i] = x;
}
int y = 0;
int z = 0;
count(arr1, num_elements, y, z);
int * negs = new int [y];
int * nonNegs = new int[z];
split(arr1, negs, nonNegs, num_elements, y, z);
cout << "Negative elements:" << endl;
print_array(negs, y);
cout << endl;
cout << "Non-Negative elements:" << endl;
print_array(nonNegs, z);
cout << endl;
All functions:
void count(int A[], int size, int & negatives, int & nonNegatives) {
for (int i = 0; i < size; ++i) {
if (A[i] < 0) {
++negatives;
}
if (A[i] >= 0) {
++nonNegatives;
}
}
}
void split(int alpha[], int bravo[], int charlie[], int aSize, int bSize, int cSize) {
int a = 0;
int b = 0;
for (int i = 0; i < aSize; ++i) {
if (alpha[i] < 0) {
alpha[i] = bravo[a];
++a;
}
else {
alpha[i] = charlie[b];
++b;
}
}
if (a + b != aSize) {
cout << "SOMETHING HAS GONE HORRIBLY WRONG!";
exit(0);
}
}
void print_array(int A[], int size) {
for (int i = 0; i < size; ++i) {
cout << A[i] << " ";
}
}
All help is appreciated.
EDIT: I apologize for my unclear question, I was wondering how to get my arrays to behave as I want them to.
Array is behaving correctly as per instruction :), you are doing minor mistake (may be overlook) in split function. I have commented out the statement and given reason of problem, please correct those two line of code, rest is fine.
void split(int alpha[], int bravo[], int charlie[], int aSize, int bSize, int cSize) {
int a = 0;
int b = 0;
for (int i = 0; i < aSize; ++i) {
if (alpha[i] < 0) {
//alpha[i] = bravo[a];// here alpha is your source array, don't overwrite it
bravo[a] = alpha[i];
++a;
}
else {
//alpha[i] = charlie[b];// here alpha is your source array, don't overwrite it
charlie[b] = alpha[i];
++b;
}
}
if (a + b != aSize) {
cout << "SOMETHING HAS GONE HORRIBLY WRONG!";
exit(0);
}
}

How to access elements of the array just by having the array's memory location? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So, this is just few methods from my myArray.cpp class. It gives me error on
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
these above code(error - which is non-class type double). can anyone please help me? I'm trying to copy an array to the object array
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
}
void myArray::setSize(int value) {
if (value > 0) {
size = value;
}
}
void myArray::setData(int index, double value) {
if ((index >= 0) && (index < size)) {
arr[index] = value;
} else {
// cout << "NO!" << endl;
}
}
double myArray::getData(int index) const {
if ((index >= 0) && (index < size)) {
return arr[index];
} else {
return arr[size - 1];
}
}
That's my main.cpp class
#include <iostream>
#include "myArray.h"
//#include "myArray.cpp"
using namespace std;
int main (int argc, char **argv)
{
cout << "**************Testing Default Constructor*****************" << endl;
myArray A1;
cout << "A1: ";
A1.print();
cout << "**************Testing Alt Constructor 1*****************" << endl;
myArray A2(5,0);
cout << "A2: ";
A2.print();
cout << "**************Testing init*****************" << endl;
A2.init();
cout << "A2 after init: ";
A2.print();
int size = 5;
double *temp = new double[size];
for(int i = 0; i < size; i++)
{
temp[i] = i;
}
cout << "**************Testing Alt Constructor 2*****************" << endl;
myArray A3(temp, size);
cout << "A3: ";
cout << A3.getSize();
cout << endl;
cout << "Fe";
A3.print();
That's my myArray.cpp class
#ifndef MYARRAY_H_INCLUDED
#define MYARRAY_H_INCLUDED
/***************************************************************************
* myArray class header file
***************************************************************************/
class myArray
{
public:
myArray();
myArray(int,double);
myArray(double*, int);
~myArray();
int getSize() const;
bool equal(const myArray &rhs) const;
void setData(int index, double value);
void insert(int, double);
void remove(int);
double get(int);
void clear();
int find(double);
bool equals(myArray&);
void print() const;
void init();
double getData(int index) const;
// void init();
// void print() const;
void expand();
private:
int size;
double *arr;
void setSize(int value);
};
#endif // MYARRAY_H_INCLUDED
That's my myArray.cpp class where I'm getting the error in the default paramaterized constructor
#include "myArray.h"
#include <iostream>
using namespace std;
myArray::myArray() : size(0) {
// size = 10;
arr = new double [size];
}
/*myArray::myArray(int _size) : size(_size) {
// size = _size;
arr = new double [size];
for (int i = 0; i < size; i++) {
arr[i] = i;
}
} */
myArray::myArray(int _size, double value) : size(_size) {
// size = _size;
arr = new double [size];
for (int i = 0; i < size; i++) {
arr[i] = value;
}
}
/*myArray::myArray(myArray* temp, int size)
{
setSize(temp.getSize());
for (int i = 0; i < getSize(); i++) {
setData(i, temp.getData(i));
}
} */
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
//double arr[size];
// arr = new double[size];
// p = orig;
// for(int i = 0;i<size;i++)
// {
// arr[i] = orig[i];
// cout << arr[i] << " ";
// }
// cout << endl;
// setSize(size);
// for (int i = 0; i < getSize(); i++)
// setData(i, orig.getData(i));
// cout << "hell";
// for (int i = 0; i < size; i++) {
// arr[i] = myArray[i];
// cout << arr[i];
//}
// arr = myArray;
}
myArray::~myArray() {
delete [] arr;
}
int myArray::getSize() const {
return size;
}
void myArray::setSize(int value) {
if (value > 0) {
size = value;
}
}
void myArray::setData(int index, double value) {
if ((index >= 0) && (index < size)) {
arr[index] = value;
} else {
// cout << "NO!" << endl;
}
}
double myArray::getData(int index) const {
if ((index >= 0) && (index < size)) {
return arr[index];
} else {
return arr[size - 1];
}
}
void myArray::print() const {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
void myArray::expand() {
double *localArray = new double[size + 1];
for (int i = 0; i < size; i++) {
localArray[i] = arr[i];
}
localArray[size] = size;
delete [] arr;
setSize(size + 1);
arr = localArray;
// myArray = new int[size];
//
// //Is this a deep-copy or a shallow-copy?
// //Can you replace one with the other?
// //What are the advantages and disadvantages?
// for(int i=0; i < size; i++) {
// myArray[i] = localArray[i];
// }
// delete [] localArray;
}
bool myArray::equal(const myArray& rhs) const {
bool result(true);
if (getSize() != rhs.getSize()) {
result = false;
} else {
for (int i = 0; i < getSize(); i++) {
if (getData(i) != rhs.getData(i)) {
result = false;
}
}
}
return result;
}
void myArray::init()
{
cout << "Enter the " << size << " elements to populate the array " << endl;
for(int i = 0;i<getSize();i++)
{
int value;
cin >> value;
setData(i,value);
}
}
Sorry I somehow I thought you wanted help with a runtime error but you want help with the compile errors.
The compile error in this part of the code
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
is specifically about the orig.getSize() part. orig is of type double* (pointer to double) and pointers do not have member functions only classes do which is why the compiler says: "which is non-class type double"
Actually there is no way in c++ to know from a pointer to how many elements it points but luckily your function already has a parameter size which i guess is meant to pass in the size of the orig array. So that line should be setSize(size);
Now two lines lower you get a similar error on setData(i,orig.getData(i)); orig is still a double* so it still doesn't have member functions. The correct way is setData(i, orig[i]);
EDIT:
BTW, i quick look through the rest of your code shows me that your setSize method doesn't allocate an array of appropriate size so you should fix that to.

Program gives a weird runtime error

#include<iostream>
using namespace std;
class darray
{
private:
int n; // size of the array
int *a; // pointer to the 1st element
public:
darray(int size)
{
n = size;
a = new int[n];
}
~darray(){ delete[] a; }
void get_input();
int get_element(int index);
void set_element(int index, int value);
int count(){ return n; }
void print();
};
void darray::get_input()
{
for (int i = 0; i < n; i++)
{
cin >> *(a + i);
}
}
int darray::get_element(int index)
{
if (index == -1)
index = n - 1;
return a[index];
}
void darray::set_element(int index,int value)
{
a[index] = value;
}
void darray::print()
{
for (int i = 0; i < n; i++)
{
cout << a[i];
if (i < (n - 1))
cout << " ";
}
cout << endl;
}
// perform insertion sort on the array a
void insertion_sort(darray d)
{
int v = d.get_element(-1); // v is the right-most element
int e = d.count() - 1; // pos of the empty cell
// shift values greater than v to the empty cell
for (int i = (d.count() - 2); i >= 0; i--)
{
if (d.get_element(i) > v)
{
d.set_element(e,d.get_element(i));
d.print();
e = i;
}
else
{
d.set_element(e, v);
d.print();
break;
}
}
}
int main()
{
int s;
cin >> s;
darray d(s);
d.get_input();
insertion_sort(d);
system("pause");
return 0;
}
I use the darray class to make a array of size n at runtime. This class gives basic functions to handle this array.
This programs says debugging assertion failed at the end.
It gives this error after ruining the program.Other than that the program works fine. What is the reason for this error ?
You need to declare and define a copy constructor:
darray::darray(const darray& src)
{
n = src.n;
a = new int[n];
for (int i = 0; i < n; i++)
{
*(a + i) = *(src.a + i);
}
}

Why is my code in C++ so much slower than my code in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
So far, I wrote my code in C (performance is of utmost importance). However, I would like to start writing my algorithms in a generic way. So, I decided to try out C++. I took a simple code in C and translated it into C++ with templates. To my disappointment, the C++ code runs 2.5 times slower. (the C code is compiled with gcc -O3; the C++ code is compiled with g++ -O3)
Am I doing something wrong in C++? Why is there such a performance hit?
Here is the C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static int df_output = 0;
int nCalls = 0;
typedef struct {
int *pancakes;
int n;
} STATE;
STATE **solution;
void shuffle(STATE *s) {
int i;
for (i = 0; i < s->n; i++) {
int i1 = rand() % s->n;
int i2 = rand() % s->n;
int temp = s->pancakes[i1];
s->pancakes[i1] = s->pancakes[i2];
s->pancakes[i2] = temp;
}
}
STATE *copyState(STATE *s) {
STATE *res = malloc(sizeof(STATE));
res->n = s->n;
res->pancakes = (int *)malloc(res->n * sizeof(int));
memcpy(res->pancakes, s->pancakes, res->n * sizeof(int));
return res;
}
// reverse n pancakes
void makeMove(STATE *s, int n) {
int i;
for (i = 0; i < n/2; i++) {
int temp = s->pancakes[i];
s->pancakes[i] = s->pancakes[n - 1 - i];
s->pancakes[n - 1 - i]=temp;
}
}
void printState(STATE *s) {
int i;
printf("[");
for (i = 0; i < s->n; i++) {
printf("%d", s->pancakes[i]);
if (i < s->n - 1)
printf(", ");
}
printf("]");
}
int heuristic(STATE *s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s->n; i++)
if (abs(s->pancakes[i]-s->pancakes[i-1])>1)
res++;
if (s->pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) printf("\t");
}
int df(STATE *s, int g, int left) {
int h = heuristic(s), i;
if (g == 0) printf("Thereshold: %d\n", left);
if (df_output) {
tabs(g);
printf("g=%d,left=%d ", g, left); printState(s); printf("\n");}
if (h == 0) {
assert(left == 0);
solution = (STATE **)malloc((g+1) * sizeof(STATE *));
solution[g] = copyState(s);
return 1;
}
if (left == 0)
return 0;
for (i = 2; i <= s->n; i++) {
makeMove(s, i);
if (df(s, g+1, left-1)) {
makeMove(s, i);
solution[g] = copyState(s);
return 1;
}
makeMove(s, i);
}
return 0;
}
void ida(STATE *s) {
int threshold = 0, i;
while (!df(s, 0, threshold)) threshold++;
for (i = 0; i <= threshold; i++) {
printf("%d. ", i);
printState(solution[i]);
printf("\n");
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
STATE *s = (STATE *)malloc(sizeof(STATE));
int i, n;
int myInstance[] = {0,5,4,7,2,6,1,3};
s->n = 8;
s->pancakes = myInstance;
printState(s); printf("\n");
ida(s);
printf("%d calls to heuristic()", nCalls);
return 0;
}
Here is the C++ code:
#include <iostream>
#include "stdlib.h"
#include "string.h"
#include "assert.h"
using namespace std;
static int df_output = 0;
int nCalls = 0;
class PancakeState {
public:
int *pancakes;
int n;
PancakeState *copyState();
void printState();
};
PancakeState *PancakeState::copyState() {
PancakeState *res = new PancakeState();
res->n = this->n;
res->pancakes = (int *)malloc(this->n * sizeof(int));
memcpy(res->pancakes, this->pancakes,
this->n * sizeof(int));
return res;
}
void PancakeState::printState() {
int i;
cout << "[";
for (i = 0; i < this->n; i++) {
cout << this->pancakes[i];
if (i < this->n - 1)
cout << ", ";
}
cout << "]";
}
class PancakeMove {
public:
PancakeMove(int n) {this->n = n;}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
int bf(PancakeState &);
PancakeMove *getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
int Pancake::bf(PancakeState &s) {
return s.n - 1;
}
PancakeMove *Pancake::getMove(int i) {
return new PancakeMove(i + 2);
}
// reverse n pancakes
void Pancake::makeMove(PancakeState &s, PancakeMove &m) {
int i;
int n = m.n;
for (i = 0; i < n/2; i++) {
int temp = s.pancakes[i];
s.pancakes[i] = s.pancakes[n - 1 - i];
s.pancakes[n - 1 - i]=temp;
}
}
void Pancake::unmakeMove(PancakeState &state, PancakeMove &move) {
makeMove(state, move);
}
int Pancake::heuristic(PancakeState &s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s.n; i++)
if (abs(s.pancakes[i]-s.pancakes[i-1])>1)
res++;
if (s.pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) cout << "\t";
}
template <class Domain, class State, class Move>
class Alg {
public:
State **solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
void ida(Domain &d, State &s);
};
template <class Domain, class State, class Move>
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
cout << "Thereshold:" << this->threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
solution = (State **)malloc((g+1) * sizeof(State *));
solution[g] = s.copyState();
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
Move *move = d.getMove(i);
d.makeMove(s, *move);
if (this->df(d, s, g+1)) {
d.unmakeMove(s, *move);
solution[g] = s.copyState();
delete move;
return 1;
}
d.unmakeMove(s, *move);
delete move;
}
return 0;
}
template <class Domain, class State, class Move>
void Alg<Domain, State, Move>::ida(Domain &d, State &s) {
int i;
this->threshold = 0;
while (!this->df(d, s, 0)) threshold++;
for (i = 0; i <= threshold; i++) {
cout << i << ".";
this->solution[i]->printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
Pancake *d = new Pancake();
PancakeState *s = new PancakeState();
int myInstance[] = {0,5,4,7,2,6,1,3};
s->pancakes = myInstance;
s->n = 8;
s->printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
alg->ida(*d, *s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
You have a lot of malloc() and operator new calls in there. Stop doing that, and performance will improve. And don't use malloc() in C++, use operator new always.
For example, PancakeMove is a small, trivial struct. But you allocate instances of it dynamically, which is slow. Just pass it around by value.
Basically, you are allocating a lot of small things on the heap instead of on the stack. That's pretty "expensive", so will take extra time.
This code (which is modified from your original code) runs within 1ms of the C code:
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <vector>
using namespace std;
static int df_output = 0;
int nCalls = 0;
class PancakeState {
public:
PancakeState(int n) : n(n), pancakes(n)
{
}
PancakeState(int n, int *v) : n(n), pancakes(n)
{
for(int i = 0; i < n; i++)
pancakes[i] = v[i];
}
PancakeState(): n(0) {}
public:
vector<int> pancakes;
int n;
PancakeState *copyState();
void printState();
};
void PancakeState::printState() {
int i;
cout << "[";
for (i = 0; i < this->n; i++) {
cout << this->pancakes[i];
if (i < this->n - 1)
cout << ", ";
}
cout << "]";
}
class PancakeMove {
public:
PancakeMove(int n) : n(n) {}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
int bf(PancakeState&);
PancakeMove getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
int Pancake::bf(PancakeState& s) {
return s.n - 1;
}
PancakeMove Pancake::getMove(int i) {
return PancakeMove(i + 2);
}
// reverse n pancakes
void Pancake::makeMove(PancakeState &s, PancakeMove &m) {
int i;
int n = m.n;
for (i = 0; i < n/2; i++) {
int temp = s.pancakes[i];
s.pancakes[i] = s.pancakes[n - 1 - i];
s.pancakes[n - 1 - i]=temp;
}
}
void Pancake::unmakeMove(PancakeState &state, PancakeMove &move) {
makeMove(state, move);
}
int Pancake::heuristic(PancakeState &s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s.n; i++)
if (abs(s.pancakes[i]-s.pancakes[i-1])>1)
res++;
if (s.pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) cout << "\t";
}
template <class Domain, class State, class Move>
class Alg {
public:
vector<State> solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
void ida(Domain &d, State &s);
};
template <class Domain, class State, class Move>
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
cout << "Thereshold:" << threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
solution.resize(g+1);
solution[g] = s;
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
Move move = d.getMove(i);
d.makeMove(s, move);
if (this->df(d, s, g+1)) {
d.unmakeMove(s, move);
solution[g] = s;
return 1;
}
d.unmakeMove(s, move);
}
return 0;
}
template <class Domain, class State, class Move>
void Alg<Domain, State, Move>::ida(Domain &d, State &s) {
int i;
this->threshold = 0;
while (!this->df(d, s, 0)) threshold++;
for (i = 0; i <= threshold; i++) {
cout << i << ".";
solution[i].printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
Pancake d = Pancake();
int myInstance[] = {0,5,4,7,2,6,1,3};
PancakeState s(8, myInstance);
s.printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
alg->ida(d, s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
As an extra benefit of not making so many direct allocations, it also doesn't leak 22 lumps of memory throughout the execution, which is quite a useful feature.
(If you want to see what changed, here's a diff - ignoring whitespace only changes):
--- pcake.orig.cpp 2014-04-13 15:43:24.861417827 +0100
+++ pcake.cpp 2014-04-13 15:42:25.145165372 +0100
## -1,7 +1,9 ##
#include <iostream>
-#include "stdlib.h"
-#include "string.h"
-#include "assert.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <vector>
+
using namespace std;
static int df_output = 0;
## -9,21 +11,22 ##
class PancakeState {
public:
- int *pancakes;
+ PancakeState(int n) : n(n), pancakes(n)
+ {
+ }
+ PancakeState(int n, int *v) : n(n), pancakes(n)
+ {
+ for(int i = 0; i < n; i++)
+ pancakes[i] = v[i];
+ }
+ PancakeState(): n(0) {}
+public:
+ vector<int> pancakes;
int n;
PancakeState *copyState();
void printState();
};
-PancakeState *PancakeState::copyState() {
- PancakeState *res = new PancakeState();
- res->n = this->n;
- res->pancakes = (int *)malloc(this->n * sizeof(int));
- memcpy(res->pancakes, this->pancakes,
- this->n * sizeof(int));
- return res;
-}
-
void PancakeState::printState() {
int i;
cout << "[";
## -37,25 +40,25 ##
class PancakeMove {
public:
- PancakeMove(int n) {this->n = n;}
+ PancakeMove(int n) : n(n) {}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
- int bf(PancakeState &);
- PancakeMove *getMove(int);
+ int bf(PancakeState&);
+ PancakeMove getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
-int Pancake::bf(PancakeState &s) {
+int Pancake::bf(PancakeState& s) {
return s.n - 1;
}
-PancakeMove *Pancake::getMove(int i) {
- return new PancakeMove(i + 2);
+PancakeMove Pancake::getMove(int i) {
+ return PancakeMove(i + 2);
}
// reverse n pancakes
## -91,7 +94,7 ##
template <class Domain, class State, class Move>
class Alg {
public:
- State **solution;
+ vector<State> solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
## -102,30 +105,28 ##
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
- cout << "Thereshold:" << this->threshold << "\n";
+ cout << "Thereshold:" << threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
- solution = (State **)malloc((g+1) * sizeof(State *));
- solution[g] = s.copyState();
+ solution.resize(g+1);
+ solution[g] = s;
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
- Move *move = d.getMove(i);
- d.makeMove(s, *move);
+ Move move = d.getMove(i);
+ d.makeMove(s, move);
if (this->df(d, s, g+1)) {
- d.unmakeMove(s, *move);
- solution[g] = s.copyState();
- delete move;
+ d.unmakeMove(s, move);
+ solution[g] = s;
return 1;
}
- d.unmakeMove(s, *move);
- delete move;
+ d.unmakeMove(s, move);
}
return 0;
}
## -138,23 +139,22 ##
for (i = 0; i <= threshold; i++) {
cout << i << ".";
- this->solution[i]->printState();
+ solution[i].printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
- Pancake *d = new Pancake();
- PancakeState *s = new PancakeState();
+ Pancake d = Pancake();
int myInstance[] = {0,5,4,7,2,6,1,3};
- s->pancakes = myInstance;
- s->n = 8;
- s->printState(); cout << "\n";
+ PancakeState s(8, myInstance);
+ s.printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
- alg->ida(*d, *s);
+ alg->ida(d, s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
+