Archived

This topic is now archived and is closed to further replies.

QBomb

When can you *not* create a std::vector?

Recommended Posts

Hi all, I''ll start with some background info. This is the ctor for class Deck.
Deck::Deck()
{
	int numCards = 56;

	std::string suits[4];
	std::string names[14];

	int suitsIndex, namesIndex;

	suits[0] = "Spades";
	suits[1] = "Diamonds";
	suits[2] = "Hearts";
	suits[3] = "Clubs";

	names[0] = "One";
	names[1] = "Two";
	names[2] = "Three";
	names[3] = "Four";
	names[4] = "Five";
	names[5] = "Six";
	names[6] = "Seven";
	names[7] = "Eight";
	names[8] = "Nine";
	names[9] = "Ten";
	names[10] = "Jack";
	names[11] = "Queen";
	names[12] = "King";
	names[13] = "Ace";

	for( suitsIndex = 0; suitsIndex < 4; suitsIndex++ )
	{
		for( namesIndex = 0; namesIndex < 14; namesIndex++ )
		{
			Card * newCard = new Card();
			newCard->suit = suits[suitsIndex];
			newCard->name = names[namesIndex];
			cards.push_back( newCard );
		}
	}
}
 
This is some temporary shuffling code.
int Deck::shuffle()
{
	int seed = 1000;
	int index, index2;
	double randNum;  //returned from rand()
	int boundary = numCards;    //upper boundary for generation
	double randomValueDouble;
	int randomValueInt;
	int *alreadyChosen;
	bool taken = true;

	std::vector< Card * > shuffleDeck(numCards);

	srand(seed);

	alreadyChosen = new int[numCards];

	for( index = 0; index < numCards; index++ )
		alreadyChosen[index] = 0;
	
	
	std::vector< Card *  >::iterator originalIter = cards.begin();

	index2 = 0;


	while( originalIter != cards.end() )
	{	
		index = 0;
		//pick a new random position
		while( taken )
		{		
			randNum = ( (double)rand() / (double)(RAND_MAX+1) );
			randomValueDouble = (randNum * boundary);
			randomValueInt = (int) randomValueDouble;

			if( alreadyChosen[randomValueInt] == 1 )
			{
				taken = true;
			}
			else
			{
				alreadyChosen[randomValueInt] = 1;
				taken = false;
			}
			
		}
		//insert current card from original deck into this position in shuffleDeck
		
		shuffleDeck.at(randomValueInt) = *originalIter;
		++originalIter;
		taken = true;
		index2++;
	}

	//copy over...
	cards.assign( shuffleDeck.begin(), shuffleDeck.end() );

	delete [] alreadyChosen;

	return 1;
}
 
std::vector< Card * > shuffleDeck(numCards); This line crashes the program... I have a class called HoldemPoker which has an instance of class Deck. From this, I can print the contents of the deck, so the constructor is filling it, but when I call the shuffle method, it bombs at that line. Is there something I''m missing here? I have a default constructor for the class Card, so I should be able to specify how many elements I want shuffleDeck to have, right? Any thoughts or suggestions are appreciated. Quent

Share this post


Link to post
Share on other sites
That line is fine. If it''s crashing, there must be an error somewhere else in your program. Such errors can be hard to track down. It helps if you strip the program down to something which is smaller, but still crashes. Look carefully over anywhere that you access an array. If you access an array outside of its bounds, that might be the cause of this crash.

Less importantly, with a regular deck of cards, ''ace'' is another name for ''one''. Also, your shuffle function could just be:

int Deck::shuffle()
{
std::random_shuffle(cards.begin(), cards.end());
}

Share this post


Link to post
Share on other sites
I''m just guessing here, but wouln''t it be possible that then you construct with a number (which you are doing) to create the fixed number of cards, that it also tries to call a constructor or something? ... in a pointer that seems impossible.

Did you try a codetrace to see what''s causing the problem inside the stl lib?

As a sidenote, what a beutiful game texas hold''em is, I actually used to program such a game for work you know. Too bad the project got canceled after the beta release. You can find a screenshot of it on flipcode''s IOTD if you search through it :-)

Albert Sandberg

Share this post


Link to post
Share on other sites
Thanks! I figured a function like that existed, and many thanks for pointing it out.

When I try to debug in VC++ 6, (is this what you mean by codetrace?) it ends up pointing me to this...


// TEMPLATE FUNCTION _Construct
template inline
void _Construct(_T1 _FARQ *_P, const _T2& _V)
{new ((void _FARQ *)_P) _T1(_V); }


So I'm guessing this has to do with the (numCards) part of the line thats crashing?

I previously used this same code successfully in another setup where I was only testing Deck.cpp. The only difference was that I had an implicit


Deck * gameDeck = new Deck()


in main.cpp, and filled the cards vector from main.cpp. After that, the shuffle function worked fine.

(If I need to post any other code that might be beneficial, let me know )

[edited by - QBomb on July 28, 2003 3:09:14 AM]

Share this post


Link to post
Share on other sites
One other quick question.

Does std::vector::clear() call destructors on the elements it removes from a vector? You might have noticed that I fill that vector with instances of class Card which currently are not being deleted.

Share this post


Link to post
Share on other sites
It''ll destruct the objects if you store them by value, but not if you store pointers to them. I tend to store them by value.
Other alternatives are to delete them manually (although you have to consider exception safety), or to use a smart pointer class, such as Boost''s shared_ptr.

Share this post


Link to post
Share on other sites