值类和结构 (C++/CX)

值结构或值类是与 Windows 运行时兼容的 POD(“纯旧数据结构”)。 它具有固定大小且只包含字段;与 ref 类不同,它没有属性。

下面的示例演示如何声明和初始化值结构。

// 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 classvalue struct 的所有成员都是公共成员并且将发送到元数据中,因此不允许标准 C++ 类型。 这与 ref 类不同,ref 类可包含 privateinternal 标准 C++ 类型。

下面的代码片段声明 CoordinatesCity 类型为值结构。 请注意,其中一个 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++ 中引用类型的工作方式相同。

当从另一种语言(如 C# 中)调用 Method1 时,无需使用 refout 关键字。 调用 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 语言参考
命名空间参考
Ref 类和结构 (C++/CX)