Поделиться через


Контейнеры STL/CLR

Библиотека STL/CLR имеет те же контейнеров, которые находятся в стандартной библиотеке C++, но она выполняется в управляемую среду платформы .NET Framework.Если вы уже знакомы с библиотекой стандартных шаблонов (STL), то STL/CLR лучший способ продолжения использования навыки, которые уже начинали при обновлении код к целевому объекту среды CLR.

Этот документ содержит общие сведения о контейнеров STL/CLR, например требования для элементов-контейнеров, типов элементов, которые можно вставить в контейнеры и проблем владения с элементами в контейнерах.При необходимости, различия между собственным стандартной библиотекой шаблонов и STL/CLR упомяните.

Требования для элементов-контейнеров

Все элементы, вставляемые в контейнеров STL должны повиноваться некоторым рекомендациям.Дополнительные сведения см. в разделе Требования для элементов-контейнеров STL/CLR.

Допустимые элементы контейнера

Контейнеры STL/CLR могут содержать один из 2 типов элементов:

  • Маркеры к ссылочным типам.

  • Ссылочные типы.

  • Unboxed типы значений.

Нельзя вставить упакованные типы значения в любые контейнеры STL/CLR.

Bb385236.collapse_all(ru-ru,VS.110).gifМаркеры к ссылочным типам

Можно ввести дескриптор к ссылочному типу в контейнер STL/CLR.Дескриптор в C++, который предназначен для среды CLR аналогичн к указателю в собственном C++.Дополнительные сведения см. в разделе Оператор дескриптора объекта (^) (расширения компонентов C++).

Bb385236.collapse_all(ru-ru,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(ru-ru,VS.110).gifСсылочные типы

Также можно вставить ссылочный тип (вместо дескриптор к ссылочному типу) в контейнер STL/CLR.Основное отличие состоит в том, что здесь, когда контейнер ссылочных типов удален, деструктор вызывается для всей внутри элементов, контейнер.В контейнере маркеров к ссылочным типам, не вызываются деструкторы для этих элементов.

Bb385236.collapse_all(ru-ru,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(ru-ru,VS.110).gifUnboxed типы значений

Можно также вставить unboxed тип значения в контейнер STL/CLR.Unboxed тип значения является типом значения, который не был помещается в упакован в ссылочный тип.

Элемент типа значения может быть одним из стандартных типов значений, например int или определяемым пользователем типом значения, такие как value class.Дополнительные сведения см. в разделе Классы и структуры (расширения компонентов C++).

Bb385236.collapse_all(ru-ru,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(ru-ru,VS.110).gifПроблемы производительности и памяти

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

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

Проблемы владения с контейнерами

Контейнеры в рабочем в семантике STL/CLR значения.Каждый раз при вставке элемента в контейнер копию этого элемента.Если необходимо получить ссылка-как семантика, можно ввести дескриптор объекта, а не сам объект.

При вызове или стираете метод clear контейнера объектов маркера, объекты, которые ссылаются на лексемы не будут освобождены из памяти.Необходимо явно удаления объекта или поскольку эти объекты находятся в управляемой куче, включите сборщик мусора освободить память, как только она определяет, что объект больше не используется.

См. также

Ссылки

Стандартная библиотека шаблонов