![]() |
An IDL array type is mapped to the corresponding C++ array definition. There is also a corresponding _var type. For example, given the following IDL definition:
typedef long LongArray [4][5];The C++ bindings provide the following definitions:
typedef CORBA::Long LongArray[4][5]; typedef CORBA::Long LongArray_slice[5]; typedef LongArray_slice* LongArray_slice_vPtr; typedef const LongArray_slice* LongArray_slice_cvPtr; class LongArray_var { public: LongArray_var(); LongArray_var(LongArray_slice*); LongArray_var(const LongArray_var&); LongArray_var & operator= (LongArray_slice*); LongArray_var & operator= (const LongArray_var &); ~LongArray_var(); const LongArray_slice& operator[] (int) const; const LongArray_slice& operator[] (CORBA::ULong) const; LongArray_slice & operator[] (int); LongArray_slice & operator[] (CORBA::ULong); operator LongArray_slice_cvPtr () const; operator LongArray_slice_vPtr& (); }; LongArray_slice * LongArray_alloc(); void LongArray_free (LongArray_slice*); LongArray_slice * LongArray_dup (const LongArray_slice*);As shown above, array mappings provide alloc, dup, and free functions (for allocating, copying, and freeing array storage), as static member functions of the class within which the array type name is scoped. The alloc function dynamically allocates an array, which can be later freed using the free function. The dup function dynamically allocates an array and copies the elements of an existing array into it. A NULL pointer can be passed to the free function. None of these functions throws exceptions.
The type of the pointer returned from LongArray_alloc is LongArray_slice*. The C++ bindings define array "slice" types for all arrays declared in IDL. The reason is that using the name LongArray in a program does not denote the array LongArray; rather, it denotes a pointer to the array. For historical reasons (related to the fact that arrays are not an actual data type in C and C++) the type of this pointer has one less array dimension than the array LongArray. Thus, the bindings for LongArray include the following typedef:
typedef string LongArray_slice[5];Hence, LongArray_slice* is the correct type for a pointer to an array of IDL type LongArray.
As with structs and sequences, arrays use special auxiliary classes for automatic storage management of String and object reference elements. The auxiliary classes for Strings and object references manage the storage just as the associated _var classes do.
When assigning a value to an array element that is an object reference, the assignment operator will automatically release the previous value (if any). When assigning an object reference pointer to an array element, the array assumes ownership of the pointer (no _duplicate is done), and the application should no longer access the pointer directly (if this is not the desired behavior, then the caller can explicitly _duplicate the object reference before assigning it.) However, when assigning to an object reference array element from a _var object or from another struct, union, array, or sequence member (rather than from an object reference pointer), a _duplicate is done automatically.
For an array of Strings, when assigning a value to an element or deleting the array, any previously held (non-null) char* is automatically freed. As when assigning to String_vars, assigning a char* to a string element does not make a copy, but assigning a const char * or another struct/union/array/sequence String element does make a copy. One should never assign a string literal (for example, "abc") to a String array element without an explicit cast to "const char*". When assigning a char* that occupies static storage (rather than one that was dynamically allocated) the caller can use CORBA::string_dup to duplicate the string before assigning it.
The following is an example that involves multidimensional arrays, and array_vars, from the IDL snippet immediately below:
typedef string s2_3[2][3]; typedef string s3_2[3][2];The code that exercises the C++ arrays that correspond to the above IDL is shown below. Notice that in the following example:
- There is no need to explicitly use slice types when working with the array _var types, because the bindings declare the pointer held by an array _var type using the appropriate slice type.
- At the end, the program explicitly frees the storage pointed to by s2_3p (using an array delete operator), but does not do this for s3_2v, because its pointer is deleted when the destructor for s3_2v is implemented. (This is the purpose of the _var types.)
#include arr_C.cpp #include stdio.h main() { int i,j; char id[40]; // create arrays s2_3_slice* s2_3p = s2_3_alloc(); s3_2_var s3_2v = s3_2_alloc(); // load the arrays for(i=0; i<2; i++) { for (j=0; j<3; j++) { sprintf(id, "s2_3 element [%d][%d]",i,j); // Use string_dup when assigning a char* // if you do not want the array to own the original: s2_3p[i][j] = CORBA::string_dup(id); } } for(i=0; i<3; i++) { for (j=0; j<2; j++) { sprintf(id, "s3_2_var element [%d][%d]",i,j); // Use string_dup when assigning a char* // if you do not want the array to own the original: s3_2v[i][j] = CORBA::string_dup(id); } } // print the array contents for(i=0; i<2; i++) { for (j=0; j<3; j++) { printf("%s\n", s2_3p[i][j]); } } for(i=0; i<3; i++) { for (j=0; j<2; j++) { printf("%s\n", s3_2v[i][j]); } } delete [] s2_3; // needed to prevent a storage leak. // Nothing is needed for s3_2v, because // it is a _var type. }Output from the above program is:
s2_3 element [0][0] s2_3 element [0][1] s2_3 element [0][2] s2_3 element [1][0] s2_3 element [1][1] s2_3 element [1][2] s3_2_var element [0][0] s3_2_var element [0][1] s3_2_var element [1][0] s3_2_var element [1][1] s3_2_var element [2][0] s3_2_var element [2][1]