Compartilhar via


Contêineres STL/CLR

A biblioteca STL/CLR tem os mesmos contêineres encontrados na biblioteca C++ padrão, mas ele é executado dentro do ambiente gerenciado do.NET Framework.Se você já estiver familiarizado com o modelo Biblioteca de STL (Standard), STL/CLR é a melhor maneira de continuar a usar as habilidades que já desenvolveram ao atualizar seu código para o common language runtime (CLR) de destino.

Este documento fornece uma visão geral dos contêineres STL/CLR, como os requisitos para elementos de contêiner, os tipos de elementos que você pode inserir em recipientes e problemas com os elementos nos recipientes de propriedade.Onde apropriado, as diferenças entre a Standard Template Library e STL/CLR nativos são mencionadas.

Requisitos para elementos de contêiner

Todos os elementos inseridos em contêineres STL devem obedecer a determinadas diretrizes.Para mais informações, consulte Requisitos para elementos de contêiner STL/CLR.

Elementos de contêiner válido

Contêineres STL/CLR podem conter um dos dois tipos de elementos:

  • Trata de tipos de referência.

  • Tipos de referência.

  • Tipos de valor desemoldurado.

Você não pode inserir tipos de valor convertidos em qualquer um dos contêineres STL/CLR.

Bb385236.collapse_all(pt-br,VS.110).gifAlças para tipos de referência

Você pode inserir um identificador para um tipo de referência em um contêiner STL/CLR.Uma alça em C++ que tem como alvo o CLR é análoga a um ponteiro em C++ nativo.Para mais informações, consulte Operador Handle to Object (^) (Extensões de Componentes C++).

Bb385236.collapse_all(pt-br,VS.110).gifExemplo

O exemplo a seguir mostra como inserir um identificador para um objeto de funcionário em um 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(pt-br,VS.110).gifTipos de referência

Também é possível inserir um tipo de referência (em vez de um identificador para um tipo de referência) em um contêiner STL/CLR.A principal diferença é que, quando um recipiente de tipos de referência é excluído, o destruidor é chamado para todos os elementos dentro desse recipiente.Em um recipiente de alças para tipos de referência, destruidores para esses elementos não seriam chamados.

Bb385236.collapse_all(pt-br,VS.110).gifExemplo

O exemplo a seguir mostra como inserir um objeto de funcionário em um 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(pt-br,VS.110).gifTipos de valor desemoldurado

Você também pode inserir um tipo de valor desemoldurado em um contêiner STL/CLR.Um tipo de valor desemoldurado é um tipo de valor que não foi box em um tipo de referência.

Um elemento de tipo de valor pode ser um dos tipos de valor padrão, como um int, ou pode ser um tipo de valor definido pelo usuário, como uma value class.Para mais informações, consulte Classes e Estruturas (Extensões de Componentes C++).

Bb385236.collapse_all(pt-br,VS.110).gifExemplo

O exemplo a seguir modifica o primeiro exemplo, tornando o funcionário um tipo de valor de classe.Este tipo de valor é inserido em um cliext::set como no primeiro exemplo.

// 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;
}

Se você tentar inserir um identificador para um tipo de valor em um recipiente, C3225 de erro do compilador é gerado.

Bb385236.collapse_all(pt-br,VS.110).gifImplicações de memória e desempenho

Você deve considerar vários fatores ao determinar a usar alças para fazer referência a tipos ou tipos de valor como elementos de contêiner.Se você decidir usar tipos de valor, lembre-se de que é feita uma cópia do elemento toda vez que um elemento é inserido no recipiente.Para pequenos objetos, isso não deve ser um problema, mas se os objetos que estão sendo inseridos são grandes, o desempenho poderá ser prejudicado.Além disso, se você estiver usando tipos de valor, é impossível armazenar um elemento em vários contêineres ao mesmo tempo, porque cada recipiente terá sua própria cópia do elemento.

Se você decidir usar alças para tipos de referência em vez disso, o desempenho pode aumentar porque não é necessário fazer uma cópia do elemento quando ele é inserido no recipiente.Além disso, diferentemente com tipos de valor, o mesmo elemento pode existir em vários recipientes.No entanto, se você decidir usar alças, você deve ter cuidado para garantir que o identificador é válido e o objeto refere-se a não foi excluído em outro lugar no programa.

Propriedade problemas com contêineres

Contêineres STL/CLR funcionam em semântica de valor.Sempre que você inserir um elemento em um recipiente, uma cópia do elemento é inserida.Se você deseja obter a semântica de referência, você pode inserir um identificador para um objeto em vez do próprio objeto.

Quando você chama a limpar ou apaga o método de um contêiner de objetos de alça, os objetos que se referem as alças não estão liberados da memória.Você deve explicitamente excluir o objeto, ou, porque esses objetos residem no heap gerenciado, permitir que o coletor de lixo liberar a memória, uma vez que ele determina que o objeto não está sendo usado.

Consulte também

Referência

Standard Template Library