STL/CLR容器

STL/CLR 库在标准 C++ 库中找到具有相同容器,但是,它在 .NET Framework 的托管环境中运行。如果您已熟悉标准模板库 (STL), STL/CLR 的最佳方式是继续使用已经开发,当升级您的代码以公共语言运行时的技能 (CLR)。

本文档提供在 STL/CLR 的容器概述,如容器元素的要求,您可以插入到容器中元素的类型,并且,所有权问题与容器的元素。在适当的时候,在本机标准模板库和 STL/CLR 之间的差异提到。

容器元素的要求

所有元素插入 STL 容器必须遵循某些准则。有关更多信息,请参见 STL/CLR容器元素的要求

活动容器元素

STL/CLR 容器可以容纳元素的两种类型之一:

  • 引用类型的句柄。

  • 引用类型。

  • 未装箱的值类型。

您不能插入装箱值类型到任何 STL/CLR 容器中。

Bb385236.collapse_all(zh-cn,VS.110).gif引用类型的句柄

您可以插入句柄引用类型。 STL/CLR 容器中。面向 CLR 在 C++ 的句柄类似于在本机 C++ 的指针。有关更多信息,请参见 对象句柄运算符 (^)(C++ 组件扩展)

Bb385236.collapse_all(zh-cn,VS.110).gif示例

下面的示例演示如何插入的句柄。 employee 对象到 cliext::set中。

// cliext_container_valid_reference_handle.cpp
// compile with: /clr

#include <cliext/set>

using namespace cliext;
using namespace System;

ref class Employee
{
public:
    // STL containers might require a public constructor, so it
    // is a good idea to define one.
    Employee() :
        name(nullptr),
        employeeNumber(0) { }

    // All STL containers require a public copy constructor.
    Employee(const Employee% orig) :
        name(orig.name),
        employeeNumber(orig.employeeNumber) { }

    // All STL containers require a public assignment operator.
    Employee% operator=(const Employee% orig)
    {
        if (this != %orig)
        {
            name = orig.name;
            employeeNumber = orig.employeeNumber;
        }

        return *this;
    }

    // All STL containers require a public destructor.
    ~Employee() { }

    // Associative containers such as maps and sets
    // require a comparison operator to be defined
    // to determine proper ordering.
    bool operator<(const Employee^ rhs)
    {
        return (employeeNumber < rhs->employeeNumber);
    }

    // The employee's name.
    property String^ Name
    {
        String^ get() { return name; }
        void set(String^ value) { name = value; }
    }

    // The employee's employee number.
    property int EmployeeNumber
    {
        int get() { return employeeNumber; }
        void set(int value) { employeeNumber = value; }
    }

private:
    String^ name;
    int employeeNumber;
};

int main()
{
    // Create a new employee object.
    Employee^ empl1419 = gcnew Employee();
    empl1419->Name = L"Darin Lockert";
    empl1419->EmployeeNumber = 1419;

    // Add the employee to the set of all employees.
    set<Employee^>^ emplSet = gcnew set<Employee^>();
    emplSet->insert(empl1419);

    // List all employees of the company.
    for each (Employee^ empl in emplSet)
    {
        Console::WriteLine("Employee Number {0}: {1}",
            empl->EmployeeNumber, empl->Name);
    }

    return 0;
}

Bb385236.collapse_all(zh-cn,VS.110).gif引用类型

也可能会插入每个引用类型 (而不是引用类型的句柄)。 STL/CLR 容器中。此处的主要区别在于,当容器引用类型时删除,析构函数为容器的所有元素对的调用。在引用类型的容器句柄,这些组件的析构函数不会调用。

Bb385236.collapse_all(zh-cn,VS.110).gif示例

下面的示例演示如何插入一个 employee 对象到 cliext::set中。

// cliext_container_valid_reference.cpp
// compile with: /clr

#include <cliext/set>

using namespace cliext;
using namespace System;

ref class Employee
{
public:
    // STL containers might require a public constructor, so it
    // is a good idea to define one.
    Employee() :
        name(nullptr),
        employeeNumber(0) { }

    // All STL containers require a public copy constructor.
    Employee(const Employee% orig) :
        name(orig.name),
        employeeNumber(orig.employeeNumber) { }

    // All STL containers require a public assignment operator.
    Employee% operator=(const Employee% orig)
    {
        if (this != %orig)
        {
            name = orig.name;
            employeeNumber = orig.employeeNumber;
        }

        return *this;
    }

    // All STL containers require a public destructor.
    ~Employee() { }

    // Associative containers such as maps and sets
    // require a comparison operator to be defined
    // to determine proper ordering.
    bool operator<(const Employee^ rhs)
    {
        return (employeeNumber < rhs->employeeNumber);
    }

    // The employee's name.
    property String^ Name
    {
        String^ get() { return name; }
        void set(String^ value) { name = value; }
    }

    // The employee's employee number.
    property int EmployeeNumber
    {
        int get() { return employeeNumber; }
        void set(int value) { employeeNumber = value; }
    }

private:
    String^ name;
    int employeeNumber;
};

int main()
{
    // Create a new employee object.
    Employee empl1419;
    empl1419.Name = L"Darin Lockert";
    empl1419.EmployeeNumber = 1419;

    // Add the employee to the set of all employees.
    set<Employee>^ emplSet = gcnew set<Employee>();
    emplSet->insert(empl1419);

    // List all employees of the company.
    for each (Employee^ empl in emplSet)
    {
        Console::WriteLine("Employee Number {0}: {1}",
            empl->EmployeeNumber, empl->Name);
    }

    return 0;
}

Bb385236.collapse_all(zh-cn,VS.110).gif未装箱的值类型

您还可以插入一个未装箱的值类型。 STL/CLR 容器中。已装箱的值类型 未装箱 到引用类型的值类型。

值类型元素可以是一个标准值类型,例如 int,也可以是用户定义的值类型,例如 value class。有关更多信息,请参见类和结构(C++ 组件扩展)

Bb385236.collapse_all(zh-cn,VS.110).gif示例

下面的示例通过雇员类值类型修改第一个示例。此值类型然后插入 cliext::set 正如在第一个示例。

// cliext_container_valid_valuetype.cpp
// compile with: /clr

#include <cliext/set>

using namespace cliext;
using namespace System;

value class Employee
{
public:
    // Associative containers such as maps and sets
    // require a comparison operator to be defined
    // to determine proper ordering.
    bool operator<(const Employee^ rhs)
    {
        return (employeeNumber < rhs->employeeNumber);
    }

    // The employee's name.
    property String^ Name
    {
        String^ get() { return name; }
        void set(String^ value) { name = value; }
    }

    // The employee's employee number.
    property int EmployeeNumber
    {
        int get() { return employeeNumber; }
        void set(int value) { employeeNumber = value; }
    }

private:
    String^ name;
    int employeeNumber;
};

int main()
{
    // Create a new employee object.
    Employee empl1419;
    empl1419.Name = L"Darin Lockert";
    empl1419.EmployeeNumber = 1419;

    // Add the employee to the set of all employees.
    set<Employee>^ emplSet = gcnew set<Employee>();
    emplSet->insert(empl1419);

    // List all employees of the company.
    for each (Employee empl in emplSet)
    {
        Console::WriteLine("Employee Number {0}: {1}",
            empl.EmployeeNumber, empl.Name);
    }

    return 0;
}

如果尝试插入的句柄。值类型到容器中, 编译器错误 C3225 生成。

Bb385236.collapse_all(zh-cn,VS.110).gif性能和内存问题

,在确定使用处理引用类型或值类型作为容器元素时,您必须考虑多种因素。如果您决定使用值类型,请确保该元素的副本都将元素插入容器。对于小对象,则不应是问题,,但是,如果插入的对象时,性能可能遭受。此外,如果您使用的是,值类型,同时存储一个元素在多个容器是不可能的,因为每个容器将其元素的副本。

如果您决定使用处理引用类型,性能可能会增加,因为制作该元素是不必要的,因为它在容器中插入。此外,不同于值类型,则元素可以存在于多个容器。但是,因此,如果您决定使用处理,必须注意确保句柄是有效的,它引用的对象在程序中其他地方未被删除。

所有权问题与容器

在 STL/CLR 的容器处理值语义。在将元素插入到容器中,元素的副本插入时间。如果要获取类似于引用的语义,也可以插入句柄对象而不是对象。

当您调用清除或清除一个容器的方法处理对象时,处理引用的对象不会从内存中释放。则必须显式删除对象,或者,在中,因为这些对象位于托管堆,使垃圾回收器释放内存,一旦确定不再使用对象。

请参见

参考

标准模板库