Moving the contents of one vector to another - c++

So I have a vector:
vector<Enemy*> enemies;
This vector hold enemies, which are created dynamically throughout the game.
if(rand() % 1000 > 998)
{
Enemy * enemy = new Enemy(num_of_enemies);
enemies.push_back(enemy);
}
The problem with this being is that the vector is ever growing even if the enemy has been deleted, which is slowing down my game.
Essentially I want to move the contents of the vector to a new one, but only the elements that actually hold an enemy.
I read that there was something called std::move but I'm not really sure how to implement it properly, or if it will successfully move the elements that contain enemies, and not just the whole vector.
Any help with code implementation of structuring would be greatly appreciated.

Here’s a complete workflow of how to handle spawning and despawning enemies. Note that there are no pointers at all involved.
Spawning an enemy:
if (if random_float_between_0_and_1() < 0.002)
enemies.push_back(Enemy{arguments});
Despawning enemies; according to your comment below, should look something like this:
auto last_iter = std::remove_if(enemies.begin(), enemies.end(), is_dead);
enemies.erase(last_iter, enemies.end());
Here, is_dead is a function that takes an Enemy const& and determines whether it collided with a player or the screen bounds:
bool is_dead(Enemy const& enemy) {
return outside_screen_area(enemy) or near_player(enemy);
}
The functions outside_screen_area and near_player should be straightforward for you to implement.
To understand how the code above works, consult the documentations of std::remove and std::vector::erase.
Another thing: implement the function random_float_between_0_and_1 in terms of the standard library random library that ships with C++11. Don’t use std::rand or modulo operations on integer random numbers, they work badly (i.e. they’re not truly uniformly distributed and will give skewed results).

The problem with this being is that the vector is ever growing even if the enemy has been deleted ...
Essentially I want to move the contents of the vector to a new one ...
It seems to me that a simpler approach would be to remove the pointers to deleted objects from the original vector instead of making a copy.
There is no difference between a pointer to a deleted object that no longer exists and a pointer to an existing object. Therefore you must keep track of the elements that must be removed from the vector. The simplest solution is to remove the element immediately after it has been deleted. This becomes much easier with smart pointers since removing the pointer also deletes the object automatically.
std::move won't help you with this problem.
You may want to consider not using manual dynamic allocation at all. You can instead store Enemy objects in the vector.
When the enemy is to be deleted I call the class destructor, and than [sic] I delete
delete expression calls the destructor. Calling it yourself also will have undefined behaviour.

First of all, I suggest you shouldn't use a data structure like std::vector if you want to remove a single element in a random position. The complexity of this operation is linear on the number of elements after the deleted element.
As I understand, you have a number of enemies moving around a 2D screen side by side with one (or many) player(s). If an enemy is hit by a player or goes out of the screen, it will be deleted. You just loop over the list of enemies to see these conditions fulfilled.
In this case, I recommend you to use std::map to manage your created enemy objects.
Suppose that your Enemy class has a function to check deletion conditions, e.g:
bool Enemy::willbeDeleted() /* if true then will be deleted */
then here is a class using std::map to manage your enemy objects:
EnemyManager.hpp
#include <map>
class EnemyManager {
public:
/*
* Get the Enemy Manager
*/
static EnemyManager& Instance();
/*!
* Delete the instance of EnemyManager
*/
static void deleteInstance();
public:
/* Create an enemy object */
void createEnemy();
/* Check all enemy objects and delete any fulfulling condition */
void checkEnemy();
virtual ~EnemyManager();
private:
/* Make sure we can not call EnemyManager constructor directly */
EnemyManager();
EnemyManager(const EnemyManager& objManager);
/* Instance of EnemyManager */
static EnemyManager* enemyManager;
private:
/* List of current enemy objects */
std::map<int, A*> enemyList_;
/* Identity of already-create object, it increases on creating a new object */
int enemyIndex_;
};
EnemyManager.cpp
#include "EnemyManager.hpp"
#include <vector>
EnemyManager* EnemyManager::enemyManager = 0;
EnemyManager& EnemyManager::Instance()
{
if (0 == enemyManager)
{
enemyManager = new EnemyManager();
}
return *enemyManager;
}
void EnemyManager::deleteInstance()
{
if (0 != enemyManager) delete enemyManager;
}
EnemyManager::EnemyManager() : enemyList_(), enemyIndex_(0)
{}
EnemyManager::~EnemyManager() {
/* Nothing todo */
}
void EnemyManager::createEnemy()
{
enemyList_[enemyIndex_] = new Enemy();
++enemyIndex_;
}
void EnemyManager::checkEnemy()
{
std::map<int, A*>::const_iterator itb = enemyList_.begin(),
ite = enemyList_.end(), it;
// Vector containing id of enemy object to delete
std::vector<int> enemyToDelete;
for (it = itb; it != ite; ++it)
if ((it->second)->willbeDeleted())
enemyToDelete.push_back(it->first);
// Delete enemies and remove them from map
for (std::size_t idx = 0; idx < enemyToDelete.size(); ++idx)
{
delete enemyList_[enemyToDelete[idx]];
enemyList_.erase(enemyToDelete[idx]);
}
}
you can use this class as follow :
in main.cpp
EnemyManager& enemyManager = EnemyManager::Instance();
if(rand() % 1000 > 998)
{
/* Create new enemy */
enemyManager.createEnemy();
}
/* Check all enemies */
enemyManager.checkEnemy();
There are two important functions: createEnemy controls the way to create a new Enemy object, checkEnemy verifies objects and deletes them if needed and the size of enemyList_ won't increase forever :)
I believe with this approach, deleting enemies won't slow down your program anymore.
One of a drawback of this approach is that the number of created objects can be limited by 2^(8*sizeof(enemyIndex_))

Related

Can't push_back a class into an object vector inside a for loop

I cannot call a function that does a push_back into a vector
void GameState::InitialiseBullet(float x, float y, float vx, float vy)
{
Bullet* bullets = new Bullet();
bullets->SetSize(5.f, 20.f);
bullets->AddFrame("./images/bullet.png");
bullets->Play();
bullets->SetX(x);
bullets->SetY(y);
bullets->velocityX = vx;
bullets->velocityY = vy;
bullets->isActive = true;
gameObjects.push_back(bullets);
}
when it is inside the following for loop
for (auto& object : gameObjects)
{
//Determine the type at runtime
if (dynamic_cast<Player*>(object) != 0)
{
//Process player-specific logic
PlayerLogic(dynamic_cast<Player*>(object), a_fTimeStep);
}
//Determine the type at runtime
if (dynamic_cast<Bullet*>(object) != 0)
{
//Process bullet-specific logic
BulletLogic(dynamic_cast<Bullet*>(object), a_fTimeStep);
}
if (dynamic_cast<Enemy*>(object) != 0)
{
//Process enemy-specific logic
Enemy* enemy = dynamic_cast<Enemy*>(object);
EnemyLogic(enemy, lowerAliens);
if (enemy->GetIsActive() == true)
{
allDead = false;
}
}
//Update and draw our objects
object->Update(a_fTimeStep);
object->Draw();
}
The piece of code that calls the function:
if (createBullet == true)
{
InitialiseBullet(bulletX, bulletY, 0, 500);
createBullet = false;
}
That code works when outside the for loop. However, I need the for loop to provide access to each of my player, enemy and bullet objects. Is there a way to push_back to a vector inside a for loop that is based on the same vector? I get a "Expression: Vector iterators incompatible" error when it's inside the loop. Any ideas? New to C++ programming.
It looks like you are pushing into the same vector you are iterating, that means, you are forcing items realocation and iterator invalidation; in other words - your data moves to different location and used iterator becomes invalid.
I rarely see situation where you really need to iterate and append same vector, so take a look into your code again.
If you really need to do that, iterate this way:
for (size_t i = 0; i < gameObjects.size(); ++i)
{/*Some code*/}
Also using this method you should use gameObjects[i]. instead of it->
It's just a vector of pointers, so it's not very big.
The objects being added is probably even smaller.
You could make a copy of the vector and iterate over the copy while inserting into the real one.
You could put new items into a new, empty vector while you iterate, and then splice them onto the real one at the end.
To delete objects, you could do either of those things, or you could simply set a flag "isZombie" and then remove all the zombies at the end.
These aren't the only answers, but they all work.
When using iterators to loop through your vector you can't in this 'for-loop' modify the vector.
A quick google gave me this; which seemd to fit your case pretty well.
Probably because the push_back ... caused an internal
reallocation in the vector thus all its iterators were invalidated.
Source: http://www.cplusplus.com/forum/beginner/64854/
Do I understand you right when I'm assuming your using iterators due to your error message.
One question you should ask yourself is why you would ever want to add instances to this vector, maybe you should rethink your design slightly to avoid this.

C++ - Adding objects to an std::vector, instantiated in a loop

I'm an expert level Java programmer, trying to port my knowledge over to C++. This is not homework, just a concept that I'm trying to learn the C++ equivalent of.
What I'm trying to do, is "generate" a list of objects of a custom type using a loop. This is how I would do it in Java:
public class TestClass
{
private ArrayList<ExampleClass> _exampleObjects;
private int _numObjects = 10;
public void populateList()
{
_exampleObjects = new ArrayList<ExampleClass>();
for(int i = 0; i < _numObjects; i++)
{
_exampleObjects.add(new ExampleClass());
}
}
public void doStuffWithListItems()
{
for(ExampleClass e : _exampleObjects)
{
e.performAction();
}
}
}
Super simple stuff. Create a list, iterate through an arbitrary loop and add objects to it. Then, loop through those objects and use them for whatever purpose.
TestClass.h:
class TestClass
{
public:
// Constructor, copy constructor, destructor definitions
void populateList();
void doStuffWithListItems();
private:
std::vector<ExampleClass> _exampleObjects;
const int _numObjects = 10;
};
TestClass.cpp:
void TestClass::populateList()
{
for(int i = 0; i < _numObjects; i++)
{
ExampleObject obj;
_exampleObjects.push_back(obj);
/* What actually goes here in place of obj? */
}
}
void TestClass::doStuffWithListItems()
{
for(auto it = _exampleObjects.begin(); it != _exampleObjects.end(); it++)
{
/* What do i do with my iterator to access my object? */
}
}
Its my understanding that where I initialise my objects in the first loop, they go out of scope and die by the end of each loop iteration. Is that right? If so, how do I make a persistent instance?
I experimented with the shared_ptr<> from and was apparently able to store them persistently, but couldn't for the life of me work out how to dereference from an iterator of a shared_ptr<>.
I feel like this should be a really simple concept. I just can't seem to work it out. I've read a lot on C++ scope and loops. I just can't seem to find anything on both.
ExampleObject obj;
_exampleObjects.push_back(obj);
/* What actually goes here in place of obj? */
Nothing. What you have is correct, assuming ExampleClass has a working copy constructor. If your compiler supports C++11 (and since you're using auto, it at least partially does), you can save yourself a copy.
_exampleObjects.emplace_back();
This constructs an object in place in the vector, forwarding the arguments (none in this case) to a matching constructor (the default ctor, in this case). For accessing the object from the iterator, do this:
for(auto it = _exampleObjects.begin(); it != _exampleObjects.end(); it++)
{
it->performAction();
}
Again, C++11 can make things better here.
for(auto & obj : _exampleObjects)
{
obj.performAction();
}
Its my understanding that where I initialise my objects in the first
loop, they go out of scope and die by the end of each loop iteration.
Correct.
If so, how do I make a persistent instance?
vector<>::push_back takes care of this. It copies the parameter into the vector. In other words, it's not the same object that was created in the loop, it's a copy. You just need to ensure that ExampleClass has non-broken copy semantics.
couldn't for the life of me work out how to dereference from an
iterator of a shared_ptr<>
If you had an iterator into a vector of shared pointers, (call it it), you would dereference it, and call the member function of the stored object, like this:
(*it)->performAction();
// alternatively
(**it).performAction();
The ideal answer suggests a very bad idea - use post increment ++ on iterator in loop.
You should never ever use it in loops where you only need to iterate because postincrement must return the value the iterator had before it was incrementing; so, that previous value needs to be copied somewhere before.
It is just not good from performance perspective and a bad codestyle sign.

Can't Save structure content

I have the next problem:
I created the structure:
struct Series : vector<Candle>
{
Security Sec;
int LookFor;
int TF;
int Corrector;
string ID;
int line;
Series(){};
Series (int _lookfor);
void Update();
};
Constructor:
Series::Series (int _lookfor)
{
LookFor=_lookfor;
for (int i = 1; i<=LookFor; i++)
{
Candle cantype = Candle(i);
push_back(cantype);
}
}
So, then we call this construcor it fills object by candle-values. LookFor - is a number of candles in the vector-series.
After initialization i want update this serie (if there is more new candle, i want delete last one and insert new on the begining of vector-serie)
void Series::Update()
{
if (size()==LookFor)
{
if (newer(cantype,c1))
{
Candle cantype = Candle(1);
Candle c1 = at(0);
pop_back();
emplace(begin(),cantype);
}
}
I need to initialize a vector of these series:
vector vec;
vec.push_back(Series(3));
And constructor does its job, everithing is fine.
But then i update them:
for (size_t x =0; x<=size()-1;x++) vec[x].Update();
I have a problem: it cann't save changes in vector. In Update method everithing is fine, it inserts needed candle in itself, but then method is ended - the state of vector (each element of vec) has no changes. In method we see changes, but after it vector become after constructor-like, the state still the same.
Tell me, please, what am I doing wrong?
As others already mentioned, do not derive from these containers (could cause nasty errors like missing dtor calls and memory leaks, no virtual destructor is present in these containers). Instead, add the vector as a member or leave it as is, if you do private inheritance.
You may use the iterator interface for such containers:
for(std::vector<Series>::iterator sIt = vec.begin();sIt != vec.end();++sIt) sIt->Update();
For your task, consider using a deque or a list as a circular buffer instead of the vector for the Candles. It would perform better for insertions and therefore allows you to use push_front() instead of emplace() or insert().
Alternatively, you could hold an index of the vector element just past the last element (which should be the first) and just assign the new candle, et voilà, you've got a dense circular buffer.
There are implementations of such circular buffers, for example the one of boost:
http://www.boost.org/doc/libs/1_52_0/libs/circular_buffer/doc/circular_buffer.html
Despite logic issues, which could prevent the modification in certain states, I can't see, why your code doesn't work at all, at least not when I went through the snippets you posted.

C++ adjacency list of pointers and structs

Working on adjacency list --> directed weighted graph
One class looks like this, i.e. header:
class CGraph;
class CMap {
public:
//voided constructors and destructors
//functions one is:
void SetDirGraph(string commands);
private:
CGraph* m_myMap;
};
Second class:
class CNode {
public:
//voided constructor and desctructor
int m_distance, m_vert;
bool m_isKnown;
};
typedef struct edges {
int v2, weight;
} edge;
class CGraph {
public:
CGraph(int map_size);
~CGraph(void);
void AddMap(int v1, int v2, int weight);
void AddEndVert(int v2, int weight);
private:
list<edge> List;
int size;
public:
CNode* verts;
};
I'm reading vertices from a file, and that works. My problem is I am having trouble creating an adjacency list based on the code given. I'm trying to use pointers first that points to a list and it is not working correctly. I don't know how to create my pointers to the list without writing over them.
void CMap::SetDirGraph(string command) {
istringstream buffer(command)
char ch;
int num, vert1, vert2, weight; //specify vertices and weight and number of vertices
buffer>>ch; //throw away first character (not needed)
buffer>>num // size of vertices
while(!buffer.eof()) { // keep reading until end of line
buffer>>v1; // vertex start
buffer>>v2; // vertex end
buffer>>weight;
m_myMap = new CGraph(map_size); //initialize m_myMap.
m_myMap->verts->m_vert = v1; // mymap->verts->vert points to first edge
m_myMap->AddMap(v1, v2, weight); // create list?
m_myMap->AddEndVert(v2, weight); //create list? push v2 and weight on my list using my list.
}
}
I've tried several different ways and I keep confusing myself, any point in the right direction would be awesome.
EDIT:
I have more code too if needed to be produced, just publishing the main stuff.
What I mean by "not working" is that I am just writing over the previous vertex. I don't know if I should create an array using m_myMap (tried and still writes over and get a memory error as well). No compiler errors.
I don't know how to create my pointers to the list without writing over them.
Apart from your application, the answer to this question is the new operator, which I assume you are aware of, since you used it within your example code. Code like int * a = new int(42); allocates memory for an int on the heap and you are responsible for cleaning it up when it is not needed anymore. You thereby have full control over how long a variable will be available. In int x = 42; int * a = &x; on the other hand, x will automatically be cleaned up when it runs out of scope, and a will be a pointer to a memory block that has no meaningful data in it anymore. If you try to dereference it, you will encounter undefined behavior, and, if you are lucky, your program will blow up.
If you can use the C++11 standard, or a library that offers smart pointers, you should prefer those over managing the pointer yourself whenever possible. A smart pointer is an object that holds the allocated memory and frees it automatically when it is destructed. More specific information depends heavily on which sort of smart pointer you are using. The reason for using smart pointers is that doing the management yourself is tedious and error prone. If you do not delete your pointers you had allocated, your application will keep on allocating more memory until it blows up some day (depending on how often and how much memory you allocate); this is called leaking. If you call delete more than once, your program will bail out as well. Here is an example of C++11 shared_ptr in your application:
class CMap
{
private:
std::shared_ptr<CGraph> m_myMap;
// etc.
};
// in SetDirGraph
m_myMap.reset( // if the smart pointer has previously been managing
// memory, it will free it before allocating new
new CGraph(map_size) // allocate CGraph as before
);
Besides that, what hopefully answers your question, I have run into several potential problems concerning your code:
Definitely wrong:
In SetDirGraph you set m_myMap->verts->m_vert = v1. m_myMap->verts is a pointer. You have freshly created m_myMap and thus verts is not initialized, hence pointing at a random block of memory. You then try to dereference it by m_myMap->verts->m_vert = v1. This cannot work. You need to create verts first, i.e. verts = new CNode;.
typedef struct edges { /* etc */ } edge; is a C construct and there is no need for the typedef wrapper in C++. It does work and all, but it is really redundant and lots of those constructs just pollute the namespace you are working in.
Do you really need pointers in the first place? Your provided snippets do not hint at why you would need to use them. You will want to reduce usage of pointers to a minimum (or at least use smart pointers, see above)

Is the use of vectors of pointers here unnecessary or worse, cause memory leaks?

I am relatively new to C++ programming, but am a C programmer of 10 years so am more comfortable with pointers to objects than I am with references to objects.
I'm writing a Solitaire game - is this design unsafe? Is there a better way?
Anyway, I have a class SolitaireGame:
class SolitaireGame:
{
public:
SolitaireGame( int numsuits = 1 );
private:
Deck * _deck;
vector<Card> _shoe;
};
The Deck is defined thus:
class Deck:
{
public:
Deck::Deck( vector<Card>& shoe );
~Deck();
int DealsLeft() const { return deals_left; }
Card * PullCard();
private:
int deals_left;
int num_each_deal;
deque<Card *> _cards;
};
The Deck constructor, takes a reference to a vector of Card objects ( the shoe, normally 104 cards ) and pushes a pointer to each card onto it's own deque of pointers.
Deck::Deck( vector<Card>& shoe )
{
vector<Card>::iterator iter = shoe.begin();
while( iter != shoe.end() )
{
_cards.push_front( &(*iter) );
iter++;
}
}
}
The shoe is created in the SolitaireGame constructor. Once this vector of dynamically created Card objects has been created - I then pass a reference to this vector to the constructor.
SolitaireGame::SolitaireGame( int numsuits ):_numsuits(numsuits )
{
Card * c;
vector<Card> _shoe;
for( int i = 0; i < NUM_CARDS_IN_SHOE; i++ )
{
c = new Card();
_shoe.push_back( *c );
}
_deck = new Deck( _shoe );
}
My idea was that the shoe would be the container for the actual memory for the Card objects and the Deck and Columns just handle pointers to those Card objects.
Just taking this snippet of code, you leak dynamically created cards.
Card * c;
vector<Card> _shoe;
for( int i = 0; i < NUM_CARDS_IN_SHOE; i++ )
{
c = new Card();
_shoe.push_back( *c );
}
_shoe.push_back( *c ) adds a copy of the Card object pointed to by c to the vector of Cards. You then fail to delete the original Card as created in the line before.
Allocating a vector of NUM_CARDS_IN_SHOE Cards can much more simply be achieved like this:
std::vector<Card> _shoe( NUM_CARDS_IN_SHOE );
Looking at your card structure, it looks like you have (or nearly have) strict ownership between objects so I don't think that you need to dynamically create your Cards.
Note that your local variable _shoe is shadowing the class variable _shoe. This probably isn't what you want as the local _shoe which you pass to the Deck constructor will go out of scope at the end of the constructor.
If you reorder you variables in SolitaireGame, you can probably do something like this:
class SolitaireGame:
{
public:
SolitaireGame( int numsuits = 1 );
private:
vector<Card> _shoe;
Deck _deck;
};
SolitaireGame::SolitaireGame( int numsuits )
: _shoe(NUM_CARDS_IN_SHOE)
, _deck(_shoe)
{
}
I've changed _deck from being a pointer. I'm using the fact that member variables are constructed in the order declared in the class definition, so _shoe will be fully constructed before it is passed as a reference to the constructor for _deck. The advantage of this is that I have eliminated the need to dynamically allocate _deck. With no uses of new, I know that I can't have any missed calls to delete as nothing needs to be deallocated explicitly.
You are right that you can store pointers to the Cards in _shoe in your _deck without any memory management issues, but note that you must not add or remove any of the Cards in the _shoe during the lifetime of the game otherwise you will invalidate all of the pointers in _deck.
I think there're two mistakes:
When you do _shoe.push_back( *c );, you're creating a copy of the Card object, so the memory reserved to c will never be freed. Btw, you should always check that for each new exists a complementary delete. Where is your delete?
In your Deck constructor you're saving pointers to objects that reside in the stack (vector<Card> _shoe;), so as soon as the SolitaireGame constructor ends, they will be deleted and your pointers will be invalid. EDIT: I see you've got another _shoe in your class, so it's not necessary to declare another _shoe local variable, in fact just by not declaring it you will solve this issue.
I hope this helps you a bit.
Initial thoughts:
In class SolitaireGame, you declare _shoe as:
vector<Card> _shoe;
but in the constructor you push heap objects on to it like this:
c = new Card();
_shoe.push_back( *c );
So, you need to declare it like this:
vector<Card*> _shoe;
You don't initialise variables in constructors, such as deals_left and num_each_deal in class Deck. I'll assume you left it out to not clutter up the code, but it's a good idea.
Class SolitaireGame creates and owns the Deck objects. It also has a Deck with pointers to SolitaireGame's Card objects. The ownership here is unclear - who deleted them? While having pointers to objects in multiple containers will work, it can make debugging more difficult, as there's scope for multiple deletion, using after it's been deleted, leaks etc. Perhaps the design could be simplified. Perhaps have Deck own the Card objects initially, and when they're removed, they get put into the vector in SolitaireGame, and don't exist in both at the same time.
In the constructor for SolitaireGame, you declare another vector of cards, which shadows the one declare in the class declaration. When you push the Card objects onto it, they'll not get pushed to the correct vector, which will go out of scope at the end of the constructor, and your class member will be empty. Just get rid of it from the constructor.
Anyway, I need a cup of tea. After that I'll take another look and see if I can suggest anything else.
I don't think the new keyword should appear anywhere in the code of these classes, and I don't see why you'd go through the trouble to share cards through pointers. Storing addresses of items held in a vector is recipe for disaster - you need to guarantee that there will be no modifications to the vector after you take the addresses, as it tends to move things around in memory without telling you.
Assuming a Card object doesn't store anything besides one or two ints, it would be a lot simpler to work with copies and values.
_deck = new Deck( _shoe );
Again, I don't see a slightest reason to increase complexity of the program by allocating an object containing two ints and a deque dynamically.
If you are worried about cost of copying some of the larger classes you have (which I would estimate has zero impact on perceived performance here), then simply don't copy them, and pass them around by const reference (if you don't need to mutate the instance), or non-const reference/pointer otherwise.
This program will leak memory , Want to find out why ? or how ?
push_back
Do remember this call do not insert your supplied element , But creates a copy of it for own use. Read this for detail
So
Card *c = new Card(); // This is on heap , Need explicit release by user
If you change it to
Card c; // This is on stack, will be release with stack unwinding
Copy below program and execute it, {I simply added logging}, try with both option, above
#include<iostream>
#include <vector>
#include <deque>
using namespace std;
const int NUM_CARDS_IN_SHOE=120;
class Card
{
public:
Card()
{
++ctr;
cout<<"C'tor callend: "<<ctr<<" , time"<<endl;
}
~Card()
{
++dtr;
cout<<"D'tor called"<<dtr<<" , time, num still to release: "<<((ctr+cpy)-dtr)<<endl;
}
Card& operator=(const Card & rObj)
{
return *this;
}
Card (const Card& rObj)
{
++cpy;
cout<<"Cpy'tor called"<<cpy<<endl;
}
private:
static int ctr,dtr,rest,cpy;
};
int Card::ctr;
int Card::dtr;
int Card::rest;
int Card::cpy;
class Deck
{
public:
Deck::Deck( vector<Card>& shoe );
~Deck();
int DealsLeft() const { return deals_left; }
Card * PullCard();
private:
int deals_left;
int num_each_deal;
std::deque<Card *> _cards;
};
Deck::Deck( vector<Card>& shoe )
{
vector<Card>::iterator iter = shoe.begin();
while( iter != shoe.end() )
{
_cards.push_front( &(*iter) );
iter++;
}
}
class SolitaireGame
{
public:
SolitaireGame( int numsuits = 1 );
private:
Deck * _deck;
std::vector<Card> _shoe;
};
SolitaireGame::SolitaireGame( int numsuits )
{
Card * c;
vector<Card> _shoe;
for( int i = 0; i < numsuits; i++ )
{
c = new Card();
_shoe.push_back( *c );
}
_deck = new Deck( _shoe );
}
int main()
{
{
SolitaireGame obj(10);
}
int a;
cin>>a;
return 0;
}
Since such a game object always has its own deck you should consider making the Deck object a real member inside SolitairGame -- not just a pointer. This will make life-time management of the deck object much simpler. For example, you won't need a custom destructor anymore. Keep in mind that STL containers contain copies. If you write something like
myvector.push_back(*(new foo));
you have a memory leak.
In addition, storing pointers to elements of a vector is dangerous because the pointers (or iterators in general) might become invalid. For a vector this is the case when it needs to grow. An alternative is std::list which keeps iterators valid after insertion, deletion, etc.
Also, keep in mind that in C++ structs and classes usually get implicit copy constructors and assignment operators. Honor the rule of three. Either disallow copying and assignment or make sure that resources (including dynamically allocated memory) is properly managed.