X-Git-Url: https://mattmccutchen.net/bigint/bigint.git/blobdiff_plain/05780f4b578d6ae054be0b19b8498d32a4f16c60..00c6448a6c5fc7a68427ca1dc3f5f523563e1041:/NumberlikeArray.hh diff --git a/NumberlikeArray.hh b/NumberlikeArray.hh index 10b7262..ab0aae0 100644 --- a/NumberlikeArray.hh +++ b/NumberlikeArray.hh @@ -1,14 +1,26 @@ /* * Matt McCutchen's Big Integer Library -* http://mysite.verizon.net/mccutchen/bigint/ */ +/* +* This mechanism prevents files from being included twice. +* Each file gets its own `id' (here `NUMBERLIKEARRAY'). +* When `#include'd, this file checks whether its `id' has +* already been flagged. If not, it flags the `id' and +* loads the declarations. +*/ #ifndef NUMBERLIKEARRAY #define NUMBERLIKEARRAY +// An essential memory-management constant. +// I wish this were built into C++ just as it is in Java. +#ifndef NULL +#define NULL 0 +#endif + /* -* A NumberlikeArray object holds a dynamically -* allocated array of Blocks. It provides certain basic +* A NumberlikeArray object holds a dynamically +* allocated array of Blk. It provides certain basic * memory management features needed by both BigUnsigned * and BigUnsignedInABase, which are both derived from it. * @@ -29,27 +41,60 @@ class NumberlikeArray { public: typedef unsigned int Index; // Type for the index of a block in the array + static const unsigned int N; // The number of bits in a block, defined below. // FIELDS Index cap; // The current allocated capacity of this NumberlikeArray (in blocks) Index len; // The actual length of the value stored in this NumberlikeArray (in blocks) Blk *blk; // Dynamically allocated array of the blocks + /* + * Change made on 2005.01.06: + * + * If a zero-length NumberlikeArray is desired, no array is actually allocated. + * Instead, `blk' is set to `NULL', and `cap' and `len' are zero as usual. + * + * `blk' is never dereferenced if the array has zero length. Furthermore, + * `delete NULL;' does nothing and causes no error. Therefore, we can use + * `NULL' as if it were a zero-length array from `new'. + * + * This is a great convenience because the only code that need be changed + * is the array allocation code. All other code will still work fine. + */ + // MANAGEMENT - NumberlikeArray(int, Index c) : cap(c), len(0) { // Creates a NumberlikeArray with a capacity - blk = new Blk[cap]; + NumberlikeArray(Index c) : cap(c), len(0) { // Creates a NumberlikeArray with a capacity + blk = (cap > 0) ? (new Blk[cap]) : NULL; } void allocate(Index c); // Ensures the array has at least the indicated capacity, maybe discarding contents void allocateAndCopy(Index c); // Ensures the array has at least the indicated capacity, preserving its contents - NumberlikeArray() : cap(0), len(0) { // Default constructor (empty array) - blk = new Blk[0]; + /* + * Default constructor. + * + * If a class derived from NumberlikeArray knows at initializer time what size array + * it wants, it can call the first constructor listed above in an initializer. + * + * Otherwise, this default constructor will be implicitly invoked, pointing `blk' to + * `NULL', a fake zero-length block array. The derived class can allocate the desired + * array itself and overwrite `blk'; it need not `delete [] blk' first. + * + * This change fixes a memory leak reported by Milan Tomic on 2005.01.06. + * Integer-type-to-BigUnsigned (and BigInteger) conversion constructors have always + * allocated their own array of length 0 or 1 after seeing whether the input is zero. + * But when the NumberlikeArray transition occurred, these constructors contained an + * implicit initializer call to the old NumberlikeArray default constructor, which + * created a real `new'-allocated zero-length array. This array would then be lost, + * causing a small but annoying memory leak. + */ + NumberlikeArray() : cap(0), len(0) { + blk = NULL; } NumberlikeArray(const NumberlikeArray &x); // Copy constructor void operator=(const NumberlikeArray &x); // Assignment operator NumberlikeArray(const Blk *b, Index l); // Constructor from an array of blocks ~NumberlikeArray() { // Destructor - delete [] blk; + delete [] blk; // Does nothing and causes no error if `blk' is null. } // PICKING APART @@ -63,11 +108,12 @@ class NumberlikeArray { // Derived classes may wish to override these if differing arrays can // sometimes be considered equivalent. bool operator ==(const NumberlikeArray &x) const; - bool operator !=(const NumberlikeArray &x) const; + bool operator !=(const NumberlikeArray &x) const { return !operator ==(x); } }; /* +* ================================= * BELOW THIS POINT are template definitions; above are declarations. * * Definitions would ordinarily belong in a file NumberlikeArray.cc so that they would @@ -83,6 +129,9 @@ class NumberlikeArray { * so other files including NumberlikeArray will be able to generate real definitions. */ +template +const unsigned int NumberlikeArray::N = 8 * sizeof(Blk); + // MANAGEMENT // This routine is called to ensure the array is at least a