vararray class reference

This is a variable sized array


vararray (const chdata& data)

constructor, public, from vararray<T>

This initializes a vararray with the value of the specified chdata object. This is not meant for general use. In fact, it really ought to be protected.

vararray (data_t* core)

constructor, public, from vararray<T>

This initializes the vararray with the specified data_t object. The data_t is reference counted, and this constructor causes the reference count to be incremented. A new ch_data object is created to hold the core. This is not meant for general use. In fact, it really ought to be protected.

vararray (vararray& other, make_alias_t alias)

constructor, public, from vararray<T>

This is a copy constructor with an extra argument. The argument's value is not used; it is meerly there for overloading. This form of copy constructor will cause this vararray to alias other, as opposed to the regular form which also shares data but sets up a lazy copy.

Alias vs. COW semantics is explained...

vararray_g()

constructor, public, from vararray_g<T>

vararray_s()

constructor, public, from vararray_s<T>


explicit vararray_g (int elcount)

constructor, public, from vararray_g<T>

explicit vararray_s (int elcount)

constructor, public, from vararray_s<T>


vararray_g (int elcount, int capacity)

constructor, public, from vararray_g<T>

vararray_s (int elcount, int capacity)

constructor, public, from vararray_s<T>


vararray_g (vararray_g& other, make_alias_t alias)

constructor, public, from vararray_g<T>

vararray_s (vararray_s& other, make_alias_t alias)

constructor, public, from vararray_s<T>


vararray_g (const T* data, int len)

constructor, public, from vararray_g<T>

vararray_s (const T* data, int len)

constructor, public, from vararray_s<T>


~vararray_g()

destructor, public, from vararray_g<T>

~vararray_s()

destructor, public, from vararray_s<T>


operator= (vararray& other)


const T& operator[] (int index) const

T& operator[] (int index)

public, from vararray<T>

This returns a reference to an element of the array.

void alias_with (vararray_g& other)

public, from vararray_g<T>

void alias_with (vararray_s& other)

public, from vararray_s<T>

This is a variation of assignment.

void append (const T& x)

public, from vararray<T>

This function appends an element to the array. The size of the array is increased by one.

void append (const vararray& other, int frompos, int fromlen)

public, from vararray<T>

This function appends a substring of the other array onto this array.

It is equivilent to replace (elcount(), 0, other, frompos, fromlen)


void debug_print() const

public, from nt_base

This function dumps a report to standard output.


void debug_snoop (snoop_t& results) const

public, from nt_base

This function is designed for use in the validation code. It provides details of the internal state that are not normally public. See the snoop_t structure, and the unit testing code.

int elcount() const

public, from nt_base

This function returns the number of elements in the vararray. That is, the legal range of indexing the collection is 0 through elcount() inclusive.

This function is called elcount because it's meaning is clear. Years ago, I was working on a project and had members in various classes called length, size, and whatnot. For collection classes, there were various names for the size, and I wanted to standardize. Upon discussing it with a co-worker, we decided that either term was unclear. elcount was decided upon because it is clearly the number of elements in a collection. Other terms could have other meanings: size in bytes, length in inches?


typedef T eltype

public, from vararray<T>

Sometimes in a collection template it is handy to get the type of the element. This typedef is provided for that purpose.

void get (T* dest, int count, int startpos=0) const

public, from vararray<T>

This function copies values out of the vararray into the dest buffer. Note that this has assignment, not constructor, semantics.

const T& get_at (int index) const

public, from vararray<T>

This gets a single value from the array.

It is better than the more general operator[] because it knows the value will be read, not written. It returns a const regardless of whether this is const, and avoids triggering a lazy copy.

T* get_buffer()

const T* get_buffer() const

public, from vararray<T>

These functions return a pointer to the internal data of the vararray.

void put (const T* src, int count, int startpos=0)

public, from vararray<T>

This copies multiple elements into the array. It does not insert -- it overwrites the current values.

void put_at (const T& val, int index)

public, from vararray<T>

This function replaces one value in the array.

void remove (int pos, int len=1)

public, from nt_base

This removes elements from the array. The elcount is reduced by len, and elements after the point of deletion are shifted up.

See also remove_all, replace.

Preconditions...

void remove_all ()

public, from nt_base

This function removes all elements from the array, producing an empty array.

void replace (int pos, int lendel, const T* data, int datalen)

public, from vararray<T>

This is the workhorse of the array manipulation functions. Starting at pos in this array, lendel elements are removed. Then datalen elements are inserted at that same position. The data parameter should point to the first element to insert (the others follow consecutivly).

The value of pos must be within the array, or may also be exactly equal to the array's length. That is, when pos == elcount() the function appends data (and lendel must be zero).

If lendel == 0, this function degenerates to an insert operation.

If datalen == 0, this function degenerates to a remove operation.


void replace (int pos, int lendel, const vararray& other, int frompos, int fromlen)

public, from vararray<T>

This form of replace inserts from another vararray object. The substring of other that is inserted starts at index frompos and has a length of fromlen. It is legal for other to be the same object as this.

void reserve (int newcapacity)

public, from nt_base

This function reserves extra room in the array, to accomidate additional growth without re-copying the values.

A vararray has two sizes associated with it: The Count is the number of elements present, and defines the legal indexing range. This is the value fetched by elcount. Each vararray also has a Capacity, which may be greater than or equal to the Count. The Capacity is how much memory is actually allocated, such that Count can be revised upward without having to reallocate and relocate the contents.

Calling reserve will increase the Capacity to match the parameter, if it is not at least that large already. It also triggers copy-on-write if it needs to increase the allocation. Note that another way for Capacity to become larger than Count is to delete items from a vararray; it will resize downward without reallocating the storage.

A subsequent resize will not need to reallocate storage if the new size fits in the available capacity (which is always the case if resizing it to be smaller!) and it does not need to perform a copy-on-write (that is, the data is not being shared).

Any of the splicing functions, including replace, replace_all, append, sorted_insert, truncate, remove, and remove_all, will perform the operation in-place, moving only elements to the right of the insertion/deletion, and not reallocate, if:

Use of reserve can make code like the following much more efficient:

void foo (vararray<int& A>)
 {
 const int iterations= 1000000;
 A.reserve (iterations + A.elcount());
 for (int loop= 0;  loop < iterations;  ++loop)
    A.append (loop);
 }

Without the call to reserve, the above code will reallocate the array a million times, each time having to re-copy the entire result thus-far. By reserving room in advance, each call to append extends the Count and copies only one element.

Note that reserved space takes up memory. For example, if the code above performed A.remove(0,999998), Count would become 2 but Capacity would still be a million! This is great if Iím amout to insert a bunch of stuff, but a waste if the capacity is caused by deleting and will not be used again. There is no function provided simply to force a reallocation and reclaim unneeded reserved space. The reserve function will increase the Capacity if it needs to, but if the argument is smaller than the existing Capacity, will do nothing. One work around is to do this:

{ // extra braces for scope
vararray_s<int> temp (A);  // now A and temp are sharing internal representation
A.remove (0,999998);  // will reallocate A, since it triggers a copy-on-write
} // temp goes away, freeing the million elements.

void resize (int newsize)

public, from nt_base

This function changes the elcount of an array. If the array shrinks, remaining elements hold their values. If the array grows, additional default-initialized elements are appeneded.

See also: truncate


int sorted_insert (const T& value, int (*compare)(const T&, const T&))

public, from vararray<T>

This function inserts the value into the array. It figures out the position by itself, assuming that the array is being maintained in sorted order. The function compare describes the relationship by returning a negative number for "less than", a positive number for "greater than", and zero for "equal" (just like strcmp).

The return value is the element's index. That is, it tells you where the element was inserted.


void truncate (int newsize)

public, from nt_base

This function is used to efficiently shrink the array.

See also: resize



Page content copyright 1997 by John M. Dlugosz. Home:http://www.dlugosz.com, email:mailto:john@dlugosz.com