Array of pointers to an abstract class - c++

I'm having a problem assigning pointers to an array of pointers in my program. I have it setup so that the function accepts a pointer as an argument and I tried to assign that pointer to an index of the array. It compiles fine, but it does not run, I get a segfault.
The error comes from EventHeap::push, the first line in the function.
You guys have any ideas?
I appreciate the help.
Edit: I'll post the specific problem right down below, but I'll just leave the code just in case below it :D
The segfault occurs in the push function, first line.
void ModemSimV2::nextCall( int delta ){
static int nextCallTime = 0;
static int userNum = 0;
Event *e;
e = new Dialin( userNum++, nextCallTime );
eventSet->push( e );
nextCallTime += delta;
}
//push function takes a pointer to an Event and puts into the array
void EventHeap::push( Event *e ) {
array[size] = e;
reIndex( size );
size++;
}
Source:
// ModemSimV2.cpp
//
// #author David Harrigan
// dtk24
//
// 4/10/2012
//
#include "ModemSimV2.h"
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ ModemSimV2 +++++++++++++++++++++++++++
// Constructor for ModemSim.
ModemSimV2::ModemSimV2( int modems, double avgLen, int callIntrvl )
: freeModems( modems ), avgCallLen( avgLen ),
freqOfCalls( callIntrvl ), r( (int) time( 0 ) )
{
nextCall( freqOfCalls ); // Schedule first call
}
// Place a new DIAL_IN event into the event queue.
// Then advance the time when next DIAL_IN event will occur.
// In practice, we would use a random number to set the time.
void ModemSimV2::nextCall( int delta ){
static int nextCallTime = 0;
static int userNum = 0;
Event *e;
e = new Dialin( userNum++, nextCallTime );
eventSet->push( e );
nextCallTime += delta;
}
// Run the simulation until stopping time occurs.
void ModemSimV2::runSim( int stoppingTime ){
Event *e;
int i = 0;
while( ! eventSet->empty( ) ){
e = eventSet->pop();
if ( e->getTime() > stoppingTime )
break;
if ( e->process( *this ) )
eventSet->push( e );
nextCall( freqOfCalls );
i++;
}
}
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Event +++++++++++++++++++++++++++++
//Constructor for event
Event::Event(){
}
//copy constructor
Event::Event( const Event &e ) {
*this = e;
}
//virtual destructor
Event::~Event( ) {
}
//operator overloads
bool Event::operator > ( const Event & rhs ) const {
return time > rhs.time;
}
bool Event::operator < ( const Event & rhs ) const {
return time < rhs.time;
}
bool Event::operator <= ( const Event & rhs ) const {
return time < rhs.time;
}
bool Event::operator != ( const Event & rhs ) const {
return time != rhs.time;
}
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Dialin +++++++++++++++++++++++++++++
//inhereited constructor
Dialin::Dialin (int name, int tm )
: time( tm ), who( name ) {
return;
}
//copy constructor
Dialin::Dialin ( const Dialin &d ) {
*this = d;
}
//destructor
Dialin::~Dialin( ) {
}
//bool process - unfinished
bool Dialin::process( ModemSimV2 &m ) {
cout << "User " << who << " dials in at time "
<< time << endl;
if( m.freeModems > 0 ) {
m.freeModems--;
int howLong = r.negExp( m.avgCallLen );
cout << " and connects for " << howLong <<
" minutes " << endl;
time += howLong;
return true;
}
else {
cout << "but gets busy signal" << endl;
return false;
}
}
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++++ Hangup +++++++++++++++++++++++++++++
//inhereited constructor
Hangup::Hangup (int name, int tm )
: time( tm ), who( name ) {
return;
}
//copy constructor
Hangup::Hangup ( const Hangup &h ) {
*this = h;
}
//destructor
Hangup::~Hangup ( ) {
}
//bool process - unfinished
bool Hangup::process( ModemSimV2 &m ) {
m.freeModems++;
cout << "User " << who << " hangs up at time "
<< time << endl;
return false;
}
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ EventHeap ++++++++++++++++++++++++++++
//EventHeap constructor
EventHeap::EventHeap( ) {
array = new Event*[1];
size = 0;
}
//constructor
EventHeap::EventHeap( int numVals ) {
array = new Event*[numVals];
size = 0;
}
//push function takes a pointer to an Event and puts into the array
void EventHeap::push( Event *e ) {
array[size] = e;
reIndex( size );
size++;
}
//since this is a min-heap, it removes the smallest value in the array
Event* EventHeap::pop( ) {
Event *e = array[0];
array[0] = array[size - 1];
size--;
if( !empty( ) )
buildHeap(0);
return e;
}
//builds the heap once popped, to reorder the array
//
void EventHeap::buildHeap( int index ) {
int min;
if (getRight(index) >= size) {
if (getLeft(index) >= size)
return;
else
min = getLeft(index);
}
else {
if (array[getLeft(index)] <= array[getRight(index)])
min = getLeft(index);
else
min = getRight(index);
}
if (array[index] != 0 && array[index] > array[min]) {
Event *temp( array[min] );
array[min] = array[index];
array[index] = temp;
buildHeap(min);
}
}
//similar to buildHeap, but is called when a value is pushed to the array
//
void EventHeap::reIndex( int hole ) {
while( array[hole] != NULL && array[hole] < array[getParent( hole )] ) {
int pIndex = getParent( hole );
Event *temp( array[hole] );
array[hole] = array[pIndex];
array[pIndex] = temp;
hole = pIndex;
}
}
//returns true if empty
bool EventHeap::empty() const {
return ( size == 0 );
}
//returns the left child
int EventHeap::getLeft( int index ) const {
return ( index * 2 ) + 1;
}
//returns the right child
int EventHeap::getRight( int index ) const {
return ( index * 2 ) + 2;
}
//returns the parent
int EventHeap::getParent( int index ) const {
return ( index - 1 ) / 2;
}
Header:
// ModemSimV2.h
//
// #author David Harrigan
// dtk24
//
// 4/10/2012
//
#ifndef MODEM_SIM_V2_H
#define MODEM_SIM_V2_H
#include <queue>
#include <vector>
#include <functional> // for greater()
#include <climits> // for INT_MAX
#include <iostream>
#include "random.h"
using namespace std;
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ ModemSimV2 +++++++++++++++++++++++++++
class EventHeap;
class ModemSimV2 {
public:
ModemSimV2( int modems, double avgLen, int callIntrvl );
// Add a call to eventSet at the current time,
// and schedule one for delta in the future.
void nextCall( int delta );
// Run the simulation
void runSim( int stoppingTime );// = INT_MAX );
friend class Event;
friend class Dialin;
friend class Hangup;
private:
Random r; // A random source
EventHeap *eventSet; // Pending events
// Basic parameters of the simulation
int freeModems; // Number of modems unused
const double avgCallLen; // Length of a call
const int freqOfCalls; // Interval between calls
};
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Event +++++++++++++++++++++++++++++
class Event{
protected:
int who; // the number of the user
int time; // when the event will occur
friend class ModemSimV2;
Random r;
public:
Event( );
Event( const Event &e );
virtual ~Event( );
bool operator > ( const Event & rhs ) const;
bool operator < ( const Event & rhs ) const;
bool operator <= ( const Event & rhs ) const;
bool operator != ( const Event & rhs ) const;
int getTime( ) { return time; };
virtual bool process( ModemSimV2 &m ) = 0;
};
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Dialin ++++++++++++++++++++++++++++
class Dialin : public Event {
public:
Dialin( int name = 0, int tm = 0 );
Dialin( const Dialin &d );
~Dialin( );
virtual bool process( ModemSimV2 &m );
private:
int who;
int time;
};
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Hangup ++++++++++++++++++++++++++++
class Hangup : public Event {
public:
Hangup( int name = 0, int tm = 0 );
Hangup( const Hangup &h );
~Hangup( );
virtual bool process( ModemSimV2 &m );
private:
int who;
int time;
};
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ EventHeap ++++++++++++++++++++++++++++
class EventHeap{
public:
EventHeap();
EventHeap( int numIndex );
bool empty( ) const;
const int & findMin( ) const;
void push( Event *x );
Event * pop();
private:
int size; // Number of elements in heap
Event **array; // The heap array
void buildHeap( int index );
void reIndex( int hole );
int getLeft( int index ) const;
int getRight( int index )const;
int getParent( int index )const;
};
#endif

Here is a clue:
e = new Dialin( userNum++, nextCallTime );
eventSet->push( *e );
You are allocating a new object and pushing a copy of it.
Another clue:
// Constructor for ModemSim.
ModemSimV2::ModemSimV2( int modems, double avgLen, int callIntrvl )
:
r( (int) time( 0 ) ),
// what about eventSet?
freeModems( modems ),
avgCallLen( avgLen ),
freqOfCalls( callIntrvl ),
{
nextCall( freqOfCalls ); // Schedule first call
}

eventSet is declared as an EventHeap* in ModemSimV2, however you do not initialize it in the constructor. Therefore when you first use it a segfault occurs.
ModemSimV2::ModemSimV2( int modems, double avgLen, int callIntrvl )
: freeModems( modems ), avgCallLen( avgLen ),
freqOfCalls( callIntrvl ), r( (int) time( 0 ) )
{
eventSet = new EventHeap(); // <-- missing this initialization
nextCall( freqOfCalls ); // Schedule first call
}
Also to avoid memory leaks, you will need a destructors in ModemSimV2 and EventHeap to free the memory you allocate.

Related

QAbstractItemModel memory usage

I'm reading a ~2 MB json file to a QAbstractItemModel visualised by a QTreeView. Each json object converts to a row in the model. The program consumes +700 MB in memory. This ratio of storage space and memory usage is not very satisfying.
I assume, the QAbstractItemModel is responsible:
Using a very small json file, memory consumption drops to ~50 MB.
Disabling the views setModel function does not change the memory consumption significantly.
Is this the behavior to be expected? I assume not.
Is there a way to optimise the memory usage? I assume this should be handled in the models data item realisation. I attached my RowItem realisation in the following:
.h file:
class RowItem
{
public:
explicit RowItem();
virtual ~RowItem();
void setParent( RowItem * p_pParent );
void appendChild( RowItem * p_pChild );
void insertChild( int p_nRow, RowItem * p_pChild );
bool removeChild(int p_nRow);
bool replaceChild(RowItem * p_pOldChild , RowItem *p_pNewChild);
RowItem * child( int p_nRow ) const;
int rowCount() const;
int columnCount() const;
int column( const QVariant & p_grData, int p_nRole = Qt::DisplayRole ) const;
QVariant data(const int & p_nColumn, int p_nRole = Qt::DisplayRole ) const;
int row() const;
RowItem * parentItem();
bool setData( const int & p_nColumn, const QVariant & p_grData, int p_nRole = Qt::DisplayRole );
RowItem & operator=( RowItem & pSrc );
protected:
QList< RowItem * > m_pChildItems;
QList< QMap< quint8, QVariant > > m_grColList; /// #attention List index = column; value map: quint8 = p_nRole ( e.g. Qt::DisplayRole, limited to max 256), QVarinat = data
RowItem * m_pParentItem;
};
.cpp file
RowItem::RowItem() : m_pParentItem( nullptr )
{
}
RowItem::~RowItem()
{
qDeleteAll(m_pChildItems );
}
void RowItem::setParent(RowItem *p_pParent)
{
m_pParentItem = p_pParent;
}
void RowItem::appendChild(RowItem *p_pChild)
{
m_pChildItems.append(p_pChild);
p_pChild->setParent( this );
}
void RowItem::insertChild(int p_nRow, RowItem *p_pChild)
{
m_pChildItems.insert( p_nRow, p_pChild );
p_pChild->setParent( this );
}
bool RowItem::removeChild(int p_nRow )
{
if ( m_pChildItems.size() <= p_nRow ) {
return false;
}
RowItem * pChild = m_pChildItems.at( p_nRow );
delete pChild;
pChild = nullptr;
m_pChildItems.removeAt( p_nRow );
return true;
}
bool RowItem::replaceChild(RowItem * p_pOldChild, RowItem * p_pNewChild )
{
if ( ( p_pOldChild == nullptr ) || ( p_pNewChild == nullptr ) ) {
return false;
}
int nIdx = m_pChildItems.indexOf( p_pOldChild );
if ( nIdx == -1 ) {
return false;
}
m_pChildItems.replace( nIdx, p_pNewChild );
p_pNewChild->setParent( this );
return true;
}
RowItem *RowItem::child(int p_nRow) const
{
if ( ( p_nRow >= m_pChildItems.size() ) || ( p_nRow < 0 ) )
{
QLOG_ERROR() << "Requested child item not existent. m_pChildItems.size() = " << m_pChildItems.size() << "; requested item:" << p_nRow << Q_FUNC_INFO;
return nullptr;
}
return m_pChildItems.at(p_nRow);
}
int RowItem::rowCount() const
{
return m_pChildItems.count();
}
int RowItem::columnCount() const
{
return m_grColList.count();
}
int RowItem::column(const QVariant &p_grData, int /*p_nRole*/) const
{
for( int i = 0; i < m_grColList.size(); ++i ) {
const QMap< quint8, QVariant > & grRoleMap = m_grColList.at( i );
if( grRoleMap.values().contains( p_grData ) == true ) {
return i;
}
}
return -1;
}
QVariant RowItem::data(const int &p_nColumn, int p_nRole) const
{
if ( ( p_nColumn < 0 ) || ( p_nRole < 0 ) ) {
QLOG_ERROR() << "Requested invalid column or role data:" << p_nColumn << p_nRole << Q_FUNC_INFO;
return QVariant();
}
if ( m_grColList.size() <= p_nColumn ) {
QLOG_ERROR() << "Requested column does not exists. Column size is " << m_grColList.size() << "; requested was col" << p_nColumn << Q_FUNC_INFO;
return QVariant();
}
const QMap< quint8, QVariant > & grRoleMap = m_grColList.at( p_nColumn );
QVariant grValue = grRoleMap.value( p_nRole, QVariant() );
if ( ( p_nRole == Qt::EditRole ) && ( ! grValue.isValid() ) ) {
grValue = grRoleMap.value( Qt::DisplayRole, QVariant() );
}
return grValue;
}
int RowItem::row() const
{
int nRow = 0;
if ( m_pParentItem != nullptr ) {
nRow = m_pParentItem->m_pChildItems.indexOf( const_cast< RowItem* >( this ) );
}
return nRow;
}
RowItem *RowItem::parentItem()
{
return m_pParentItem;
}
bool RowItem::setData( const int & p_nColumn, const QVariant &p_grData , int p_nRole)
{
QMap< quint8 , QVariant > grRoleMap;
int nCol = p_nColumn;
if ( p_nColumn == -1 ) {
m_grColList.append( QMap< quint8 , QVariant >() );
nCol = m_grColList.size() - 1;
}
else {
// expand coloumns if required
while( m_grColList.size() <= p_nColumn ) {
m_grColList.append( QMap< quint8 , QVariant >() );
}
grRoleMap = m_grColList.at( p_nColumn );
}
grRoleMap.insert( p_nRole, p_grData );
m_grColList.replace( nCol, grRoleMap );
return true;
}
RowItem &RowItem::operator=(RowItem &p_grSrc)
{
m_grColList = p_grSrc.m_grColList;
return * this;
}

How do I create a proper Memory Poolfor a Multithreaded vector (LFSV)?

Below is an old exercise for a class that is no longer being taught at my university (Parallel Processing). The goal is to create and use a Memory Bank to speed up the Lock-Free Sorted Vector implementation. I implemented the Memory Bank myself and the goal is to set aside enough memory to use so I do not have to use new or delete in the LFSV. I believe I need a Get() function that returns the address of the memory (not sure how keep track of the unused memory) and Store should free the memory (somehow mark it as unused).
Inside LFSV (which worked perfectly fine before my intervention), the exercise explains that I should replace the new and delete with new replacement and Store(memory we want freed). How do I go about creating the Get(if this is incorrect) or the Store function to perform like a proper memory bank? I will also take any reference or memory bank examples online that you may know of because I am having trouble finding good resources related to memory banks and multithreading.
There are no errors in this program, but it returns as a "FAIL" since I did not properly manage the memory bank.
#include <algorithm>//copy, random_shuffle
#include <ctime> //std::time (NULL) to seed srand
#include <iostream> // std::cout
#include <atomic> // std::atomic
#include <thread> // std::thread
#include <vector> // std::vector
#include <mutex> // std::mutex
#include <deque> // std::deque
class MemoryBank
{
std::deque< std::vector<int>* > slots;
public:
MemoryBank() : slots(10000)
{
for (int i = 0; i<10000; ++i)
{
slots[i] = reinterpret_cast<std::vector<int>*>(new char[sizeof(std::vector<int>)]);
}
}
~MemoryBank()
{
for (unsigned int i = 0; i < slots.size(); ++i)
{
delete slots[i];
}
slots.clear();
}
void * Get()
{
return &slots;
}
void Store(std::vector<int *> freeMemory)
{
return;
}
};
class LFSV {
std::atomic< std::vector<int>* > pdata;
std::mutex wr_mutex;
MemoryBank mb;
public:
LFSV() : mb(), pdata( new (mb.Get()) std::vector<int> ) {}
~LFSV()
{
mb.~MemoryBank();
}
void Insert( int const & v ) {
std::vector<int> *pdata_new = nullptr, *pdata_old;
int attempt = 0;
do {
++attempt;
delete pdata_new;
pdata_old = pdata;
pdata_new = new (mb.Get())std::vector<int>( *pdata_old );
std::vector<int>::iterator b = pdata_new->begin();
std::vector<int>::iterator e = pdata_new->end();
if ( b==e || v>=pdata_new->back() ) { pdata_new->push_back( v ); } //first in empty or last element
else {
for ( ; b!=e; ++b ) {
if ( *b >= v ) {
pdata_new->insert( b, v );
break;
}
}
}
// std::lock_guard< std::mutex > write_lock( wr_mutex );
// std::cout << "insert " << v << "(attempt " << attempt << ")" << std::endl;
} while ( !(this->pdata).compare_exchange_weak( pdata_old, pdata_new ));
// LEAKing pdata_old since "delete pdata_old;" will cause errors
// std::lock_guard< std::mutex > write_lock( wr_mutex );
// std::vector<int> * pdata_current = pdata;
// std::vector<int>::iterator b = pdata_current->begin();
// std::vector<int>::iterator e = pdata_current->end();
// for ( ; b!=e; ++b ) {
// std::cout << *b << ' ';
// }
// std::cout << "Size " << pdata_current->size() << " after inserting " << v << std::endl;
}
int const& operator[] ( int pos ) const {
return (*pdata)[ pos ];
}
};
LFSV lfsv;
void insert_range( int b, int e ) {
int * range = new int [e-b];
for ( int i=b; i<e; ++i ) {
range[i-b] = i;
}
std::srand( static_cast<unsigned int>(std::time (NULL)) );
std::random_shuffle( range, range+e-b );
for ( int i=0; i<e-b; ++i ) {
lfsv.Insert( range[i] );
}
delete [] range;
}
int reader( int pos, int how_many_times ) {
int j = 0;
for ( int i=1; i<how_many_times; ++i ) {
j = lfsv[pos];
}
return j;
}
std::atomic<bool> doread( true );
void read_position_0() {
int c = 0;
while ( doread.load() ) {
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
if ( lfsv[0] != -1 ) {
std::cout << "not -1 on iteration " << c << "\n"; // see main - all element are non-negative, so index 0 should always be -1
}
++c;
}
}
void test( int num_threads, int num_per_thread )
{
std::vector<std::thread> threads;
lfsv.Insert( -1 );
std::thread reader = std::thread( read_position_0 );
for (int i=0; i<num_threads; ++i) {
threads.push_back( std::thread( insert_range, i*num_per_thread, (i+1)*num_per_thread ) );
}
for (auto& th : threads) th.join();
doread.store( false );
reader.join();
for (int i=0; i<num_threads*num_per_thread; ++i) {
// std::cout << lfsv[i] << ' ';
if ( lfsv[i] != i-1 ) {
std::cout << "Error\n";
return;
}
}
std::cout << "All good\n";
}
void test0() { test( 1, 100 ); }
void test1() { test( 2, 100 ); }
void test2() { test( 8, 100 ); }
void test3() { test( 100, 100 ); }
void (*pTests[])() = {
test0,test1,test2,test3//,test4,test5,test6,test7
};
#include <cstdio> /* sscanf */
int main( int argc, char ** argv ) {
if (argc==2) { //use test[ argv[1] ]
int test = 0;
std::sscanf(argv[1],"%i",&test);
try {
pTests[test]();
} catch( const char* msg) {
std::cerr << msg << std::endl;
}
return 0;
}
}
reinterpret_cast is really a "I know what I'm doing, trust me" cast. The compiler will - if possible - believe you.
However, in this case it's entirely wrong. new char[] does not return a vector<int>*.

Creating Union of Sets using Dynamic Memory Allocation

Ok, so I have been thinking about this for days and I am really unsure how to approach these problems. So I need to do the following:
create a union method (i.e. union(set)) that creates a union for two sets. This method should somehow invoke the element method, a method whose specifications are mentioned below
create an operator overloaded method (+) that represents the union of sets (not sure why they are different, but that's what the specifications ask for). This method must also invoke the union method
element (int) that checks if the elements are a part of the set, I have a method below, but I am not sure if it's right
operator overload method that adds an element to a new set
If you could address at least one of these, i would greatly appreciate it, I am really struggling to understand how to address these specifications. Thanks so much for your help!
#ifndef SET_H
#define SET_H
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
class Set{
friend ostream &operator<< ( ostream &, const Set &);
friend istream &operator>> ( istream &, Set &);
public:
Set ( int = DEFAULTSIZE ); //default constructor
Set ( const Set & ); //copy constructor
Set ( int [], int, char ); //constructor passing array of integers, size, name of set
~Set(); //destructor
//assignment operator
const Set &operator= ( const Set &);
//equality operator
bool operator== ( const Set & ) const;
//inequality operator
bool operator!= ( const Set &s1) const{
return !(*this == s1);
}
//subscript operators
int &operator[] ( int );
int operator[] ( int ) const;
//methods to find union, intersection, and difference of sets
Set Union ( Set & );
Set Intersect ( Set & );
Set Difference ( Set & );
Set operator+ ( Set & ); //to represent union of two sets
Set operator^ ( Set & ); //to represent intersection of two sets
Set operator- ( Set & ); //to represent difference between two sets
bool element ( int );
private:
static const int DELIM = -999; // delimiter to signal end of input
static const int DEFAULTSIZE = 10;
int numOfElements;
int psize; //physical size of array
int *set; //pointer array to represent set
};
#endif
//SOURCE FILE
//default constructor
Set::Set ( int s ){
if ( s > 0 )
psize = s;
else
psize = DEFAULTSIZE;
//allocate an array of specified size
set = new int[ psize ];
if(!set) {
//send an error is system cannot allocate memory
cout << "Cannot Allocate Memory, exiting program... " << endl;
exit (1);
}
for ( int i = 0; i < psize; i++){
set[i] = 0;
numOfElements = 0;
}
}
//copy constructor
Set::Set ( const Set &setToCopy): psize(setToCopy.psize){
set = new int[psize];
if(!set){
cout << "Cannot Allocate Memory, exiting program..." << endl;
exit (1);
}
for (int i = 0; i < psize; i++ ){
set[i] = setToCopy.set[i];
numOfElements = psize;
}
}
Set::~Set(){
if (set)
delete [] set;
set = NULL;
}
const Set &Set::operator= ( const Set &s1 ){
if ( &s1 != this){
if (numOfElements != s1.numOfElements){
delete [] set;
psize = numOfElements;
set = new int [psize];
if (!set){
cout << "Cannot Allocate memory, exiting program..." << endl;
exit (1);
}
}
}
//assign contents of the array on the right to the contents of the array on the left
for ( int i = 0; i < psize; i++ ){
set[i] = s1.set[i];
numOfElements = psize;
}
return (*this);
}
bool Set::operator== ( const Set &s1 ) const {
bool validate = true;
if ( numOfElements == s1.numOfElements ){
for ( int i = 0; i < numOfElements; i++){
if ( set [i] != s1.set[i] ){
validate = false;
break;
}
}
}
return (validate);
}
int &Set::operator[]( int subscript ){
if ( subscript < 0 || subscript >= psize ) {
cout << " Error, exiting program... " ;
exit (1);
}
return set[subscript];
}
bool Set::element ( int n ) {
bool validate = false;
for ( int i = 0; i < psize; i++){
if ( set[i] = n )
validate = true;
}
return (validate);
}

C++ Forward declaration error - Lvalue cannont be binded

I played around with a lot of different forward declaration combinations, this seemed like the best one. It was the only one that compiled, until I uncommented the line
e->process( this );
And I get an error from xcode that says:
non-const lvalue reference to type 'Event::ModemSimV2' cannot bind to a temporary type 'ModemSimV2'
I don't really understand what it means, any help would be appreciated.
Thanks,
Source:
#include "ModemSimV2.h"
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Event +++++++++++++++++++++++++++++
Event::Event(){
}
Event::Event( const Event &e ) {
*this = e;
}
Event::~Event( ) {
}
/*
bool Event::operator > ( const Event & rhs ) const {
return time > rhs.time;
}
bool Event::operator < ( const Event & rhs ) const {
return time < rhs.time;
}
bool Event::operator <= ( const Event & rhs ) const {
return time < rhs.time;
}
bool Event::operator != ( const Event & rhs ) const {
return time != rhs.time;
}
*/
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Dialin +++++++++++++++++++++++++++++
Dialin::Dialin (int name, int tm )
: time( tm ), who( name ) {
return;
}
Dialin::Dialin ( const Dialin &d ) {
*this = d;
}
Dialin::~Dialin( ) {
}
void Dialin::process( ModemSimV2 &m ) {
}
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ EventHeap ++++++++++++++++++++++++++++
EventHeap::EventHeap( ) {
size = 0;
}
EventHeap::EventHeap( int numVals ) {
size = 0;
}
//insert
void EventHeap::push( const Event e ) {
*array[size] = e;
reIndex( size );
size++;
}
//removes the min val
Event* EventHeap::pop( ) {
Event *e = array[0];
array[0] = array[size - 1];
size--;
if( !empty( ) )
buildHeap(0);
return e;
}
//re do
void EventHeap::buildHeap( int nodeIndex ) {
int leftChildIndex, rightChildIndex, minIndex;
Event *tmp;
leftChildIndex = getLeft(nodeIndex);
rightChildIndex = getRight(nodeIndex);
if (rightChildIndex >= size) {
if (leftChildIndex >= size)
return;
else
minIndex = leftChildIndex;
} else {
if (array[leftChildIndex] <= array[rightChildIndex])
minIndex = leftChildIndex;
else
minIndex = rightChildIndex;
}
if (array[nodeIndex] > array[minIndex]) {
tmp = array[minIndex];
array[minIndex] = array[nodeIndex];
array[nodeIndex] = tmp;
buildHeap(minIndex);
}
}
//re index
void EventHeap::reIndex( int hole ) {
while( array[hole] != NULL && array[hole] < array[getParent( hole )] ) {
int pIndex = getParent( hole );
Event *temp( array[hole] );
array[hole] = array[pIndex];
array[pIndex] = temp;
hole = pIndex;
}
}
//is Empty
bool EventHeap::empty() const {
return ( size == 0 );
}
int EventHeap::getLeft( int index ) const {
return ( index * 2 ) + 1;
}
int EventHeap::getRight( int index ) const {
return ( index * 2 ) + 2;
}
int EventHeap::getParent( int index ) const {
return ( index - 1 ) / 2;
}
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ ModemSimV2 +++++++++++++++++++++++++++
// Constructor for ModemSim.
ModemSimV2::ModemSimV2( int modems, double avgLen, int callIntrvl, EventHeap e )
: freeModems( modems ), avgCallLen( avgLen ),
freqOfCalls( callIntrvl ), r( (int) time( 0 ) )
{
eventSet = &e;
nextCall( freqOfCalls ); // Schedule first call
}
// Place a new DIAL_IN event into the event queue.
// Then advance the time when next DIAL_IN event will occur.
// In practice, we would use a random number to set the time.
void ModemSimV2::nextCall( int delta ){
static int nextCallTime = 0;
static int userNum = 0;
Event *e;
Dialin d = Dialin( userNum++, nextCallTime );
*e = d;
eventSet->push( *e );
nextCallTime += delta;
}
// Run the simulation until stopping time occurs.
void ModemSimV2::runSim( int stoppingTime ){
Event *e;
while( !eventSet->empty( ) ){
e = eventSet->pop();
if ( e->getTime() > stoppingTime )
break;
e->process( this );
nextCall( freqOfCalls );
}
}
Header:
#ifndef MODEM_SIM_V2_H
#define MODEM_SIM_V2_H
#include <queue>
#include <vector>
#include <functional> // for greater()
#include <climits> // for INT_MAX
#include <iostream>
#include "random.h"
using namespace std;
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//+++++++++++++++++++++++++++++ Event +++++++++++++++++++++++++++++
class Event{
protected:
int who; // the number of the user
int time; // when the event will occur
int what; // DIAL_IN or HANGUP
class ModemSimV2;
public:
Event( );
Event( const Event &e );
virtual ~Event( );
bool operator > ( const Event & rhs ) const;
bool operator < ( const Event & rhs ) const;
bool operator <= ( const Event & rhs ) const;
bool operator != ( const Event & rhs ) const;
int getTime( ) { return time; };
virtual void process( ModemSimV2 &m ) = 0;
};
class Dialin : public Event{
public:
Dialin( int name = 0, int tm = 0 );
Dialin( const Dialin &d );
~Dialin( );
virtual void process( ModemSimV2 &m );
private:
int who;
int time;
int what;
};
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ EventHeap ++++++++++++++++++++++++++++
class EventHeap{
public:
EventHeap();
EventHeap( int numIndex );
bool empty( ) const;
const int & findMin( ) const;
void push( const Event x );
Event * pop();
private:
int size; // Number of elements in heap
vector <Event*> array; // The heap array
void buildHeap( int index );
void reIndex( int hole );
int getLeft( int index ) const;
int getRight( int index )const;
int getParent( int index )const;
};
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx
//++++++++++++++++++++++++++ ModemSimV2 +++++++++++++++++++++++++++
class ModemSimV2{
public:
ModemSimV2( int modems, double avgLen, int callIntrvl, EventHeap e );
// Add a call to eventSet at the current time,
// and schedule one for delta in the future.
void nextCall( int delta );
// Run the simulation
void runSim( int stoppingTime );// = INT_MAX );
friend class Event;
private:
Random r; // A random source
EventHeap *eventSet; // Pending events
// Basic parameters of the simulation
int freeModems; // Number of modems unused
const double avgCallLen; // Length of a call
const int freqOfCalls; // Interval between calls
};
#endif
The problem is you put your forward declaration in the wrong place in the header. The process method thinks that ModemSimV2 belongs to Event, hence Event::ModemSimV2 in the error message. Move class ModemSimV2; out of the protected section to up above the class.
class ModemSimV2;
class Event
{
...
Also this is a pointer to ModemSimV2 and you need to dereference it before passing it to process.
e->process(*this);

BK-Tree Implementation Insertion time is more how to reduce

Following is my attempt to write BK-Tree , for 150000 word file it takes around 8 seconds
Is there any way to reduce this time.
Following is my code
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include "Timer.h"
class BkTree {
public:
BkTree();
~BkTree();
void insert(std::string m_item);
private:
size_t EditDistance( const std::string &s, const std::string &t );
struct Node {
std::string m_item;
size_t m_distToParent;
Node *m_firstChild;
Node *m_nextSibling;
Node(std::string x, size_t dist);
~Node();
};
Node *m_root;
int m_size;
protected:
};
BkTree::BkTree() {
m_root = NULL;
m_size = 0;
}
BkTree::~BkTree() {
if( m_root )
delete m_root;
}
BkTree::Node::Node(std::string x, size_t dist) {
m_item = x;
m_distToParent = dist;
m_firstChild = m_nextSibling = NULL;
}
BkTree::Node::~Node() {
if( m_firstChild )
delete m_firstChild;
if( m_nextSibling )
delete m_nextSibling;
}
void BkTree::insert(std::string m_item) {
if( !m_root ){
m_size = 1;
m_root = new Node(m_item, -1);
return;
}
Node *t = m_root;
while( true ) {
size_t d = EditDistance( t->m_item, m_item );
if( !d )
return;
Node *ch = t->m_firstChild;
while( ch ) {
if( ch->m_distToParent == d ) {
t = ch;
break;
}
ch = ch->m_nextSibling;
}
if( !ch ) {
Node *newChild = new Node(m_item, d);
newChild->m_nextSibling = t->m_firstChild;
t->m_firstChild = newChild;
m_size++;
break;
}
}
}
size_t BkTree::EditDistance( const std::string &left, const std::string &right ) {
size_t asize = left.size();
size_t bsize = right.size();
std::vector<size_t> prevrow(bsize+1);
std::vector<size_t> thisrow(bsize+1);
for(size_t i = 0; i <= bsize; i++)
prevrow[i] = i;
for(size_t i = 1; i <= asize; i ++) {
thisrow[0] = i;
for(size_t j = 1; j <= bsize; j++) {
thisrow[j] = std::min(prevrow[j-1] + size_t(left[i-1] != right[j-1]),
1 + std::min(prevrow[j],thisrow[j-1]) );
}
std::swap(thisrow,prevrow);
}
return prevrow[bsize];
}
void trim(std::string& input_str) {
if(input_str.empty()) return;
size_t startIndex = input_str.find_first_not_of(" ");
size_t endIndex = input_str.find_last_not_of("\r\n");
std::string temp_str = input_str;
input_str.erase();
input_str = temp_str.substr(startIndex, (endIndex-startIndex+ 1) );
}
int main( int argc, char **argv ) {
BkTree *pDictionary = new BkTree();
std::ifstream dictFile("D:\\dictionary.txt");
Timer *t = new Timer("Time Taken to prepare Tree = ");
std::string line;
if (dictFile.is_open()) {
while (! dictFile.eof() ) {
std::getline (dictFile,line);
trim(line);
pDictionary->insert(line);
}
dictFile.close();
}
delete t;
delete pDictionary;
return 0;
}
class Timer {
public:
Timer (const std::string &name = "undef");
~Timer (void);
private:
std::string m_name;
std::clock_t m_started;
protected:
};
Timer::Timer (const std::string &name) : m_name(name), m_started(clock()) {
}
Timer::~Timer (void) {
double secs = static_cast<double>(std::clock() - m_started) / CLOCKS_PER_SEC;
std::cout << m_name << ": " << secs << " secs." << std::endl;
}
You can reduce the time by eliminating the I/O. To test your algorithm, remove as many objects out of the equation that are not directly under the control of your program. For example, the OS controls the I/O, it is out of your control. An array of constant text removes much OS involvement (the OS still may page the array depending on OS memory allocation).
Next, most tree structures are data oriented. Their performance times depend on the data. Try three sets of data: sorted ascending, "random", and sorted descending. Note the times for each.
Look at your loops and factor out any constants. Create temporary variables in loops for constant calculations in inner loops. Remove unnecessary operations.
Lastly, if your program and algorithm is very robust, work on other projects. Optimize only if necessary.