[computer-go] C++ pointer question

Adrian Grajdeanu adriang0 at cox.net
Tue Aug 8 18:53:44 PDT 2006


Finally a question where I can help...

The solution suggested by Berk Ozbozkurt points to probably the fastest 
way. The devil is in the details though. One such class (with pointers 
allocated on constructor and deallocated on destructor) needs a copy 
constructor, as the default one provided by the compiler is inadequate. 
And when writing this copy constructor you'd need to be careful. There 
are a few options here:

1. Forbid copying. For this provide an empty body _private_ copy 
constructor and similarly an empty body _private_ assignment operator. 
Thus the compiler won't allow you to code the mistake of accidentally 
copying BitBoard objects.

2. Implement transfer semantics. Provide copy constructor and assignment 
operator that takes over the allocated chunk of memory. Like so:
BitBoard::BitBoard(const BitBoard &board) :
   bits(board.bits)
{
     board.bits = 0;
}
const BitBoard &BitBoard::operator = (const BitBoard &board)
{
     if (this == &board) return;         // very important!!!
     if (bits) delete [] bits;
     bits = board.bits; board.bits = 0;
}

3. Use reference counting. The idea is that multiple objects 
collectively own the bits array. When the refcount reaches zero only 
then it is deallocated. For this though, things can get very hairy. I 
suggest if you don't have the experience in C++ you do not attempt it. 
Instead seek an already made reputable refcounted autopointer 
implementation and use that (boost library comes to mind!). If your app 
is muti-threaded, pay attention that the autopointer is implemented in a 
thread-safe manner.


However if Berk Ozbozkurt's suggestion cannot be applied, then typically 
a fast copy can be achieved with:

memcpy(&bits[0], &temp.bits[0], board_width * sizeof(bits[0])).

(or something like it. May need to play with the count of bytes
to copy due to extra padding introduced by alignment - if any!)
(I used '&bits[0]' in case the [] is overloaded. If it is not, then
simply 'bits' will suffice.)

That is provided you're not copying objects that have non-trivial 
constructor/destructor; from your code it seems you're copying ints (or 
some like them), so this should be no problem.


Yet a 3rd alternative, that avoids all the hassles is to give up 
low-level management of arrays (and pointers) and use the std::vector 
class. It is designed to work in the most efficient possible way. I have 
had very good experience with it as it has close to zero overhead. The 
only way to make it more efficient is to hardcode at compile time the 
size of the arrays, and use memcpy like above.

As a general note on the std::vector, do stay away from 
std::vector<bool> - it is ... iffy, unless you understand it pretty 
well... All other vectors are peachy.

All the best,
Adrian




Peter Drake wrote:
> Okay, I've got this method in my BitBoard class:
> 
> void dilate() // Expand to include all adjacent points
> {
> BitBoard temp;
> temp.bits[0] = bits[0] | (bits[0] << 1) | (bits[0] >> 1) | bits[1];
> temp.bits[board_width - 1] = bits[board_width - 1] | (bits[board_width - 
> 1] << 1)
> | (bits[board_width - 1] >> 1) | bits[board_width - 2];
> for (unsigned row = 1; row < board_width - 1; row++) {
> temp.bits[row] = bits[row] | (bits[row] << 1) | (bits[row] >> 1) | 
> bits[row - 1] | bits[row + 1];
> }
> for (unsigned row = 0; row < board_width; row++) {
> bits[row] = temp.bits[row];
> }
> }
> 
> Is there some way to avoid that second for loop? I tried "this = temp" 
> and "*this = *temp", but the compiler isn't happy with either.
> 
> Thanks,
> 
> Peter Drake
> Assistant Professor of Computer Science
> Lewis & Clark College
> http://www.lclark.edu/~drake/
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> computer-go mailing list
> computer-go at computer-go.org
> http://www.computer-go.org/mailman/listinfo/computer-go/


More information about the computer-go mailing list