Классы и структуры значений (C++/CX)

Структура значений или класс значений — это совместимый с среда выполнения Windows POD ("обычная старая структура данных"). Она имеет фиксированный размер и состоит только из полей только; в отличие от класса ссылки, у нее нет свойств.

В следующих примерах показано, как объявлять и инициализировать структуры значений.

// in mainpage.xaml.h:
    value struct TestStruct
    {
        Platform::String^ str;
        int i;
    };

    value struct TestStruct2
    {
        TestStruct ts;
        Platform::String^ str;
        int i;
    };

// in mainpage.cpp:
    // Initialize a value struct with an int and String
    TestStruct ts = {"I am a TestStruct", 1};

    // Initialize a value struct that contains
    // another value struct, an int and a String
    TestStruct2 ts2 = {{"I am a TestStruct", 1}, "I am a TestStruct2", 2};

    // Initialize value struct members individually.
    TestStruct ts3;
    ts3.i = 108;
    ts3.str = "Another way to init a value struct.";

Когда переменная типа значения присваивается другой переменной, значение копируется, так что каждая из двух переменных содержит собственную копию данных. Структура значения — это структура фиксированного размера, содержащая только открытые поля данных и объявляемая с помощью ключевого слова value struct .

Класс значения похож на value struct за тем исключением, что его поля должны быть явно объявлены открытыми. Он объявляется с помощью ключевого слова value class .

Структуру значений или класс значений может содержать в виде полей только фундаментальные числовые типы, классы перечисления, Platform::String^или Platform::IBox <T>^ , где T является числовым типом или классом перечисления или классом значений или структурой. Поле IBox<T>^ может иметь значение nullptr; таким образом в C++ реализуется концепция типов значений, допускающих значения NULL.

Класс значения или структура значения, содержащие в качестве члена тип Platform::String^ или IBox<T>^ , не поддерживают memcpy.

Поскольку все члены класса value class или value struct являются открытыми и передаются в метаданные, не разрешается использовать стандартные типы C++ в качестве членов. Это отличается от классов ссылок, которые могут содержать стандартные типы C++ private или internal .

В следующем фрагменте кода типы Coordinates и City объявляются как структуры значения. Обратите внимание, что один из членов данных класса City принадлежит к типу GeoCoordinates . value struct может в качестве членов содержать другие структуры значений.

public enum class Continent 
{  
    Africa,
    Asia,
    Australia,
    Europe,
    NorthAmerica,
    SouthAmerica,
    Antarctica 
};

value struct GeoCoordinates
{
    double Latitude; //or float64 if you prefer
    double Longitude;
};

value struct City
{
    Platform::String^ Name;
    int Population;
    double AverageTemperature;
    GeoCoordinates Coordinates;
    Continent continent;
};

Передача параметров для типов значений

Если параметром функции или метода является тип значения, он обычно передается по значению. Для больших объектов это может вызвать проблемы с производительностью. В Visual Studio 2013 и более ранних версиях типы значений в C++/CX всегда передаются по значению. В Visual Studio 2015 и последующих версиях типы значений можно передавать по значению или по ссылке.

Чтобы объявить параметр, который передает тип значения по значению, используйте код, аналогичный приведенному ниже:

void Method1(MyValueType obj);

Чтобы объявить параметр, который передает тип значения по ссылке, используйте символ ссылки (&), как показано в следующем примере:

void Method2(MyValueType& obj);

Тип в Method2 является ссылкой на MyValueType и работает так же, как ссылочный тип в стандартном C++.

При вызове Method1 из другого языка, например C#, не требуется использовать ключевое слово ref или out . При вызове Method2 используйте ключевое слово ref .

Method2(ref obj);

Также можно использовать символ указателя (*) для передачи типа значения по ссылке. Поведение по отношению к вызывающим объектам в других языках совпадает (вызывающие объекты в C# используют ключевое слово ref ), но в методе тип является указателем на тип значения.

Типы значений, допускающие значение NULL

Как упоминалось ранее, класс значений или структуру значений может иметь поле типа Platform::IBox<T>^, например IBox<int>^. Это поле может иметь любое числовое значение, допустимое для типа int , или значение nullptr. Поле, допускающее значение NULL, можно передать в качестве аргумента методу, параметр которого объявлен как необязательный, или в любой другой объект, в котором тип значения не обязательно должен иметь значение.

В следующем примере показано, каким образом выполняется инициализация структуры с полем, допускающим значение null.

public value struct Student
{
    Platform::String^ Name;
    int EnrollmentYear;
    Platform::IBox<int>^ GraduationYear; // Null if not yet graduated.
};
//To create a Student struct, one must populate the nullable type.
MainPage::MainPage()
{
    InitializeComponent();

    Student A;
    A.Name = "Alice";
    A.EnrollmentYear = 2008;
    A.GraduationYear = ref new Platform::Box<int>(2012);

    Student B;
    B.Name = "Bob";
    B.EnrollmentYear = 2011;
    B.GraduationYear = nullptr;

    IsCurrentlyEnrolled(A);
    IsCurrentlyEnrolled(B);
}
bool MainPage::IsCurrentlyEnrolled(Student s)
{
    if (s.GraduationYear == nullptr)
    {
        return true;
    }
    return false;
}

Саму структуру значений можно сделать допускающей значение null аналогичным образом, как показано в следующем примере.

public value struct MyStruct
{
public:
    int i;
    Platform::String^ s;
};

public ref class MyClass sealed
{
public:
    property Platform::IBox<MyStruct>^ myNullableStruct;
};

См. также

Система типов (C++/CX)
Справочник по языку C++/CX
Справочник по пространствам имен
Классы и структуры ссылки (C++/CX)