Author: Bo Persson
Date: 12:28:44 11/26/03
Go up one level in this thread
On November 25, 2003 at 01:23:36, Hristo wrote:
>
>Considering the general state of confusion about pointer and arrays, Macaroni
>should know that using vector subscribe operator would cause the same problems
>as using a raw pointer without checking the bounds.
>char ca[10];
>vector<char> va(10); // allocate for ten elements
>
>for (int i=0; i< 20; ++i){
> ca[i] = 0; // runtime error after i > 9
> va[i] = 0; // runtime error after i > 9
>}
>
>vectors will not check out of bounds conditions when used in such way.
>However if the push_back is used then the vector will grow itself automatically,
>but performance would go out of the window.
No, why?
>
>vector<char> va(10); // allocate for 10 elements
This will create a vector with 10 empty (default constructed) elements.
>
>for (int i=0; i < 100; ++i){
> va.push_back(i);
You add 100 elements, so now there are 110.
>}
>
>
>Another way to structure the code could be:
>
>typedef struct Move{
>public:
> unsigned char from;
> unsigned char to;
>};
>
>1) Using vectors in the most simple and not very efficient way.
How is it inefficient?
>typedef std::vector<Move> MovesVector;
>
>int MoveGenerator ( int turn, MovesVector& moves ){
> Move current_move;
> moves.clear();// clear the array
std::vector clears the array by calling the destructor for its elements, as
needed, and then sets its size to zero. Your struct with two unsigned chars has
an empty destructor, so the vector does nothing.
> // Start generating moves
> // and when a move is available add it to the array
> moves.push_back(current_move);
> return moves.size();
>}
>
>
>2) Using a simple wrapper, to mainly avoid clearing the array all the time:
>
>class MyMovesArray{
>public:
> MyMovesList(int intialSize=100):
> maxStor(initialSize),
> available(0)
> {
> storage = new Move[maxStor];
> }
> ~MyMovesList(){
> if (storage)
> delete []storage;
> }
> /** allow this thing to grow */
> void grow(int howMuch){
> Move* newStorage = new Move[maxStor+howMuch];
> // copy the old content into the new storage.
> ....
> // remember the new max storage size
> maxStor += howMuch;
> // Remember the new storage
> if (storage)
> delete []storage;
> storage = newStorage;
> }
> /** Clear the contents */
> inline void clear(){
> available = 0;
> }
> //
> Move* storage;
> int maxStor;
> int available;
>};
You have just shown what std::vector would do for an element type with an empty
destructor!
The std::vector can handle "difficult" members with constructors, destructors,
and copying that throws exceptions. It can also handle simple members like Move,
where all the extra machinery will be optimized away.
How does your wrapper handle the case that new cannot allocate enough space to
grow the buffer? Can it survive a call grow(MAX_INT)?
MyMovesArray will initialize the entire array at new Move[maxStor]. std::vector
will wait until each element is used before initializing it.
>
>
>int MoveGenerator ( int turn, MyMovesArray& moves ){
> moves.clear(); // very fast.
No speed difference!
> while (moves.available < moves.maxStor){
> moves.sorage[moves.available++] = currentMove;
> // if needed grow the array.
> // brak if no more moves can be generated ...
std::vector::push_back will of course grow the vector as needed, you don't have
to kill the program. :-)
> }
> return moves.available;
>};
>
>
>
>Regards,
>Hristo
Bo Persson
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.