C++. Structures. Part 3. Working with managed-structures in the CLR. Qualifiers ref and value. Declaring structural variables. Arrays of managed-structured variables. Initializing of managed structures




Structures. Part 3. Working with managed-structures in the CLR. Qualifiers ref and value. Declaring structural variables. Arrays of managed-structured variables. Initializing of managed structures

This topic is based on the topic:


Contents


Search other websites:

1. What qualifiers are used with managed structures in the CLR?

In the CLR environment, you can use three types of structures:

  • native-structures. These are the classic C/C++ structures that are used in previous versions of different programming environments. Such structures are declared without a qualifier;
  • managed-structures. These are structures designed to work in managed memory, which is used in the CLR. In this case, pointer values can not be more then allocated memory for program.

With managed structures in Visual C++/CLR, two qualifiers are used (keywords):

  • qualifier (keyword) ref. This qualifier means that the structure is a reference type;
  • qualifier value. This qualifier means that the structure is a type-value.

2. What is the difference between ref and value qualifiers when working with structures?

If you declare an instance (variable) of a structure with a qualifier ref or value, then there are no differences. Access to elements of structures is carried out through the symbol ‘ . ‘.

The difference between qualifiers ref and value is shown in the following cases:

  • if used arrays of structural variables (see p. 5, p. 6).
  • if you use pointers to structures.

When allocating memory for a pointer to a structure with the ref modifier, this structure is placed in a managed heap and can not be placed in the native heap.

If you allocate memory for a pointer to a structure with a value modifier, then the structure can be placed in both the managed heap and the native heap.

Details about the work of pointers to managed-structures are described in the topic:

3. How does the structure of reference type (ref) work? Example

In this example, a structure is declared that describes a point on the coordinate plane. It is advisable to place the structure template in a single “*.h” file, for example “MyStruct.h”.

// MyPoint structure with qualifier ref
ref struct MyPointR
{
    int x;
    int y;
};

Declaring a variable of type MyPoint and using it from other program code (for example, the event handler for a click event on a button):

MyPointR mp;
mp.x = 23;
mp.y = 36;

4. How is the work with value-structures? Example

An example of declaring a value-structure template and its instance (variable) in the program.

// The template of MyPoint structure with qualifier 'value'
value struct MyPointV
{
    int x;
    int y;
};
...
MyPointV mpv;
mpv.x = 334;
mpv.y = 43;





5. Example of using an array of structured variables with qualifier ref. Array of ref-structures. The keyword array

If the structure is declared with the qualifier ref (reference type), then it will not be possible to declare an array of structural variables in the Visual C++/CLR environment by standard C/C++ way. That is, the following code will generate an error:

// ref-structures
MyPointR MP[5]; // - error!

To declare an array from ref-structures, the keyword ‘array’ is used. Next, we show you how to work with a MyPoint type structure (see section 4).

// ref-structures
// MyPointR MP[5]; // - error!

array <MyPointR ^> ^MP; // declaring array ref-structures

// array <MyPointR> MP2; - error, must be the character '^'

// allocating memory for an array of pointers to structures
MP = gcnew array <MyPointR ^>(5);

// allocating memory for each pointer
for (int i=0; i<5; i++)
    MP[i] = gcnew MyPointR;

// filling the array values
for (int i=0; i<5; i++)
{
    MP[i]->x = i*2;
    MP[i]->y = i*(i+1);
}

6. An example of using an array of structure variables with a value qualifier. Array of value-structures. The ‘array’ keyword
// The template of MyPointV structure with qualifier value
value struct MyPointV
{
    int x;
    int y;
};

// value-structures
array <MyPointV> ^MPV; // array declaration

//array <MyPointV> MPV2; - So it is impossible,an error.Must be a ^

// Allocating memory for 5 structures
MPV = gcnew array <MyPointV>(5);

// Filling in with values
for (int i=0; i<5; i++)
{
    MPV[i].x = i*2;
    MPV[i].y = i*i;
}

7. How to represent a string as a field in a template of a structured variable?

If a structure is declared with a ref or value qualifier, it is not possible to declare a character string in the classical way:

char s[10]; // this is error

In order to use several symbols in the template of the structural variable, one must use one of two methods:

  • declare a pointer to char;
  • declare an array of type ‘char’ using the keyword ‘array’. Then perform the appropriate conversion to a type that is handy to handle (for example, String).

Example. Let the structure template, which describes the coordinates (x, y) of the point on the plane, be given. In addition, each coordinate can have a comment. The example shows two ways for representing a character string (char type).

For the purpose of demonstrating the work, there are declared 2 variable-pointers to char that have different types of declaration of pointers.

// structure MyPointR
ref struct MyPointR
{
    int x;
    int y;
    char * sx;         // pointer to 'char' - array of characters
    array <char> ^sy; // use the keyword 'array'
};

Work with the MyPointR structure is shown below.

MyPointR mpr;

mpr.x = 23;
mpr.y = 35;
mpr.sx = new char[10]; // it works
mpr.sy = gcnew array <char>(10); // also works

strcpy(mpr.sx, "X");

mpr.sy[0] = 'Y';
mpr.sy[1] = '\0';

// conversion from array <char> to array char[10]
char buffer[10]; // additional variable
for (int i=0; i<10; i++)
    buffer[i] = mpr.sy[i];

// conversion from char[] to String for more convenient use
String ^s = gcnew String(buffer);

8. How to represent an array of numbers in a ref-structure or value-structure? Examples

In managed-structures to represent an array of numbers in the classical way

int D[10];
double F[5][10];

will not succeed

Memory for arrays must be allocated dynamically. Therefore, to work with arrays, you need to declare a pointer to the base type. For more information about the operation of pointers, see the topics:

Below are examples of how to work with arrays that are part of the ref-structure and value-structure.

Example 1. Representation of an array of n integers in a ref-structure.

// A ref-structure teimplate in which an array of n integers
// is implemented in two ways
ref struct IntArrayR
{
    int n; // Number of numbers in the array
    int * A1; // unmanaged pointer to array of integers
    array <int> ^A2; // managed-pointer to array of integers
};

Using the IntArrayR structure template

// template of the IntArrayR ref-structure
IntArrayR mA; // mA - structural variable

// There must be 5 numbers in the array
mA.n = 5;

// allocation of memory for an array of numbers int
mA.A1 = new int[mA.n];

// allocating memory for an array
mA.A2 = gcnew array <int>(mA.n);

// Filling of arrays A1 and A2 with values
for (int i=0; i<mA.n; i++)
{
    mA.A1[i] = i*3+5;
    mA.A2[i] = i*i-2;
}

// displaying the arrays to listBox1 and listBox2
listBox1->Items->Clear();
listBox2->Items->Clear();

for (int i=0; i<mA.n; i++)
{
    listBox1->Items->Add(mA.A1[i].ToString());
    listBox2->Items->Add(mA.A2[i].ToString());
}

Example 2. Declaration of an array of n real numbers in a value-structure. Find the sum of array elements.

// A template for a value-structure that implements an array of n real numbers
value struct FloatArrayV
{
    float n;   // Number of numbers in the array
    float * A1; // unmanaged pointer to array of float-numbers
    array <float> ^A2; // managed-pointer to array of float-numbers
};

Working with the FloatArrayV structure:

// Using the value structure FloatArrayV
FloatArrayV fA;

// In the structure of an array of 10 numbers
fA.n = 10;

fA.A1 = new float[fA.n]; // allocating memory for a one-dimensional array A1
fA.A2 = gcnew array <float>(10); // allocating memory for array A2

// filling array values
for (int i=0; i<fA.n; i++)
{
    fA.A1[i] = System::Math::Sin(i) + System::Math::Cos(i);
    fA.A2[i] = i*System::Math::Sqrt(i);
}

// finding the sums of array items
float sum1 = 0, sum2 = 0;
for (int i=0; i<fA.n; i++)
{
    sum1 += fA.A1[i];
    sum2 += fA.A2[i];
}

label1->Text = "sum(A1) = " + sum1.ToString();
label2->Text = "sum(A2) = " + sum2.ToString();

9. How is the assignment of managed-structures done? Example

You can only assign the value-structures, structures that are declared with a ‘value’ qualifier. In this case, the data (field values) are copied from one structure to another.

Because structures with qualifier ref are referenced structures, they can not be assigned.

Example. Assignment of value-structures.

// Assignment of value-structures
MyPoint_value mpv;

mpv.x = 300;
mpv.y = 500;
mpv.color = 5;

MyPoint_value mpv2;

mpv2 = mpv; // assignment of structures

int d;
d = mpv2.x; // d = 300

10. How is the managed-structures initialized? Example

For managed-structures, initialization can only be done for value-structures. For reference structures that begin with the word ref, the initialization can not be done.

Example 1. Initializing the structure with the qualifier value. Let the template of the structure that describes the point on the screen of the monitor be given.

// Structure declared with qualifier 'value'
value struct MyPoint_value
{
    int x;
    int y;
    int color;
};

Then the initialization of the variable (instance) of the structure will be as follows:

// initialization of value-structure
MyPoint_value mpv = { 3, 4, 5 };

Example 2. Let the Book template, which describes the book in the library, be given.

value struct BookV
{
    char * title;
    char * author;
    int year;
    float price;
};

The initialization of the structure variable will be as follows:

// initialization of value-structure
BookV bv1 = { NULL, NULL, 2002, 23.55 };
BookV bv2 = { "Title-1", "Author-1", 2000, 30.44 };

String ^s = gcnew String(bv2.title); // s = "Title-1"

11. Example of declaring and using an array of ref-structures inside a ref-structure

As you know, you can not declare an array of native-structures and value-structures in the ref-structure. In the ref-structure, you can declare only an array of ref-structures.

Let the template of the ref-structure, which describes a point on the plane that has a color, be given.

// structure is declared with qualifier ref
ref struct MyPoint_ref
{
    int x;
    int y;
    int color;
};

If you need to declare an array of MyPoint_ref points in a structure, then you need to write the following code

// A template of structure in which there is an array of points (structures)
ref struct PointsArray_ref
{
    int n; // number of points
    array <MyPoint_ref ^> ^mp;
};

In the program (another program code), you can use the Points_Array_ref template approximately as follows

// Pointer to the structure PointsArray_ref
PointsArray_ref ^pA;
pA = gcnew PointsArray_ref; // memory allocation

pA->n = 5;

// Allocating memory for pointers to MyPoint_ref
pA->mp = gcnew array <MyPoint_ref ^>(pA->n);

// Allocating memory for array elements within a struct
for (int i=0; i<pA->n; i++)
{
    pA->mp[i] = gcnew MyPoint_ref;
}

// filling structures with values
for (int i=0; i<pA->n; i++)
{
    pA->mp[i]->x = i*5+2;
    pA->mp[i]->y = i*i+3;
    pA->mp[i]->color = i;
}

// test
int d;
d = pA->mp[3]->x; // d = 3*5+2 = 17
d = pA->mp[4]->y; // d = 4*4+3 = 19

12. Example of declaring and using an array of value-structures within a value-structure

A template of the MyPoint_value structure describing the point with color in the plane is specified.

// Structure declared with qualifier 'value'
value struct MyPoint_value
{
    int x;
    int y;
    int color;
};

The template of the structure PointsArray_value, containing an array of points (structures MyPoint_value) is specified.

// Array of value-structures in structure
value struct PointsArray_value
{
    int n; // number of points
    array <MyPoint_value> ^mp;
};

Demonstration of using the structure PointsArray_value.

// Array of value-structures in structure
PointsArray_value mA;

mA.n = 5;

// Allocating memory for an array
mA.mp = gcnew array <MyPoint_value>(mA.n);

// Filling elements of structures with values
for (int i=0; i<mA.n; i++)
{
    mA.mp[i].x = i*5+2;
    mA.mp[i].y = i*i+5;
    mA.mp[i].color = i;
};

// test
int d;
d = mA.mp[3].x; // d = 17

13. Example of declaration and working with a two-dimensional array of ref structures

A ref-structure describing a point on the plane is given

ref struct MyPoint_ref
{
    int x;
    int y;
    int color;
};

Demonstration of work with a two-dimensional array of ref-structures of size 5*10

// Two-dimensional array of ref-structures. Stages of work
// 1. Declaring a variable with a name like 'two-dimensional array of ref-structures'
array <MyPoint_ref ^, 2> ^mp;

// 2. Allocation of memory for pointers to structures in an array of size 5 * 10
mp = gcnew array <MyPoint_ref ^,2>(5, 10);

// 3. Allocating memory for array elements - ref-structures MyPoint_ref
for (int i=0; i<5; i++)
    for (int j=0; j<10; j++)
        mp[i,j] = gcnew MyPoint_ref;

// 4. Filling with arbitrary values of structures
for (int i=0; i<5; i++)
    for (int j=0; j<10; j++)
    {
        mp[i,j]->x = i + j*3;
        mp[i,j]->y = i*i + j;
        mp[i,j]->color = i + j;
    }

// 5. Test
int d;
d = mp[2,4]->x; // d = 2+4*3 = 14
d = mp[0,3]->y; // d = 0*0+3 = 3
d = mp[3,8]->color; // d = 3+8 = 11

14. An example of declaring and working with a two-dimensional array of value-structures

Let the value-structure template be given

value struct MyPoint_value
{
    int x;
    int y;
    int color;
};

Then work with a two-dimensional array of such structures of size 5 * 10 will be approximately the following:

// Two-dimensional array of value-structures. Stages of work
// 1. Declaring the mp variable of type 'two-dimensional value-array MyPoint_value'
array <MyPoint_value, 2> ^mp;

// 2. Memory allocation for two-dimensional array
mp = gcnew array <MyPoint_value, 2>(5, 10);

// 3. Filling in array field values
for (int i=0; i<5; i++)
    for (int j=0; j<10; j++)
    {
        mp[i,j].x = i*i + j;
        mp[i,j].y = i*5 - j;
        mp[i,j].color = i + j*2;
    }

// 4. Test
int d;
d = mp[2,3].x; // d = 7
d = mp[3,0].color; // d = 3
d = mp[1,2].y; // d = 3


Related topics