Mozilla has many array classes because each array is optimized for a particular usage pattern. This guide describes the available arrays as well as the enumerator classes that can be used to get to them. In this document the term Array refers to a container for multiple objects with a numeric, zero-based index.
The standard array classes are:
- nsIArray - a scriptable container for scriptable XPCOM objects. This array is read-only, and the interface does not provide any methods that will allow adding and removing members.
- nsIMutableArray - a scriptable container for scriptable XPCOM objects, which allows addition and removal of member objects. This interface actually derives from nsIArray.
- nsCOMArray<T> - a C++ class which provides a typesafe, reference-counted container for pointers to a single type of COM object. This class is more or less a wrapper around nsVoidArray and thus shares most of its semantics.
- nsVoidArray - a C++ class which provides a generic container for any objects using the generic void * type.
- nsStringArray / nsCStringArray - a set of C++ classes for holding lists of string objects. Derived from nsVoidArray
- nsAutoVoidArray - a version of nsVoidArray which includes 8 entries of internal storage for the array data.
- nsSmallVoidArray - a replacement for nsVoidArray which is optimized to hold zero or one element.
This handy chart may make it easier to understand the different arrays:
|Class||Data Type||Scriptable?||Typesafe?||Can be modified?||Built in buffer?||Ownership|
|nsIArray||XPCOM object||Yes||No||No||No||Reference Counted, Weak/Strong|
|nsIMutableArray||XPCOM object||Yes||No||Yes||No||Reference Counted, Weak/Strong|
|nsCOMArray<T>||XPCOM object||No||Yes||Yes*||No||Reference Counted, Strong|
|nsVoidArray||Any||No||No||Yes*||No||Weak / None|
|No||Yes||Yes*||No||Private (copies strings)|
|nsAutoVoidArray||Any||No||No||Yes*||Yes||Weak / None|
|nsSmallVoidArray||Any||No||No||Yes*||No||Weak / None|
|nsISupportsArray||XPCOM Object||Yes||No||Yes*||No||Reference Counted, Strong|
Note: Concrete C++ arrays can be made read-only by declaring them const. For example:
// HandleList cannot modify the array because of const void HandleList(const nsVoidArray&);
Most of the arrays presented here provide callback-style means to enumerate members of an array. Instead of incrementally accessing each element of the array by its index, the arrays provide a way to pass in a callback function that will be called for each element in the array.
For most concreted C++ classes like nsVoidArray and nsCOMArray<T>, indexing should be just as fast as the callback-style enumeration, because accessing an indexed member of such an array is usually very fast. In the case of scriptable arrays like nsIArray however, the enumeration mechanism is often preferred because it avoids the AddRef / Release overhead that comes from accessing each object.
The only functional drawback to in-place enumeration is that you cannot manipulate the array itself during the enumeration. For example, you should not delete elements of an array during the enumeration as this will often confuse the loop which is enumerating the array.
Most arrays provide access to an object which is used to enumerate members of the array. These Enumerators maintain state about the current position in the array. Enumerators are used to access the elements in an ordered way, without relying on the underlying array type. These enumerators include:
- nsISimpleEnumerator - an enumerator for COM objects.
- nsIStringEnumerator / nsIUTF8StringEnumerator - enumerators for strings
Obsolete arrays / enumerators
There are some deprecated classes which should not be used by new code.
- nsISupportsArray - obsoleted by nsIArray, use that instead.
- nsIEnumerator - obsoleted by nsISimpleEnumerator, use that instead.
- nsIBidirectionalEnumerator - obsoleted by nsISimpleEnumerator, use that instead.
Here are a few simple rules which will keep your code clean and your developers happy:
- Use typesafe arrays like nsCOMArray<T> wherever possible.
- Use enumerators for external access to internal arrays.
- Avoid all obsolete arrays and enumerators.
- Avoid creating temporary arrays.