Condividi tramite


Contenitori di STL/CLR

La libreria STL/CLR presenta gli stessi contenitori che si trovano nella libreria C++ standard, ma viene eseguito all'interno dell'ambiente gestito.NET Framework.Se è stato già familiarità con la libreria di modelli (STL) standard, STL/CLR è il modo migliore per continuare a utilizzare le competenze già compilato come ottimizzare il codice per Common Language Runtime (CLR).

In questo documento viene fornita una panoramica dei contenitori in STL/CLR, ad esempio requisiti per gli elementi contenitore, i tipi di elemento che è possibile inserire i contenitori e la proprietà pubblica con gli elementi nei contenitori.Nei casi, le differenze tra la raccolta del modello e lo STL/CLR standard nativi sono indicate.

Requisiti per gli elementi contenitore

Tutti gli elementi inseriti nei contenitori STL devono obbedire a determinate indicazioni.Per ulteriori informazioni, vedere Requisiti per gli elementi contenitore di STL/CLR.

Elementi validi del contenitore

I contenitori STL/CLR possono utilizzare uno dei due tipi di elementi seguenti:

  • Handle ai tipi di riferimento.

  • Tipi di riferimento.

  • Tipi di valore unboxed.

Non è possibile inserire i tipi valore boxed nei contenitori STL/CLR.

Bb385236.collapse_all(it-it,VS.110).gifHandle ai tipi di riferimento

È possibile inserire un handle per un tipo di riferimento in un contenitore STL/CLR.Handle in C++ destinato a CLR sono analoghe a un puntatore in C++ nativo.Per ulteriori informazioni, vedere Operatore handle a oggetto (^) (Estensioni del componente C++).

Bb385236.collapse_all(it-it,VS.110).gifEsempio

Nell'esempio seguente viene illustrato come inserire un handle a un oggetto employee in 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(it-it,VS.110).gifTipi di riferimento

È anche possibile inserire un tipo di riferimento (piuttosto che un handle per un tipo di riferimento) in un contenitore STL/CLR.La differenza principale consiste nel fatto che quando un contenitore dei tipi di riferimento viene eliminato, il distruttore viene chiamato per qualsiasi interno degli elementi che contenitore.In un contenitore di handle ai tipi di riferimento, distruttori per questi elementi non verranno chiamati.

Bb385236.collapse_all(it-it,VS.110).gifEsempio

Nell'esempio seguente viene illustrato come aggiungere un oggetto employee in 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(it-it,VS.110).gifTipi di valore unboxed

È anche possibile inserire un tipo di valore sottoposti a unboxing in un contenitore STL/CLR.Un tipo di valore sottoposti a unboxing è un tipo di valore che non è stato sottoposto a boxing in un tipo di riferimento.

Un elemento di tipo di valore può essere uno dei tipi di valore standard, ad esempio int, oppure può essere un tipo di valore definito dall'utente, come value class.Per ulteriori informazioni, vedere Classi e struct (Estensioni del componente C++).

Bb385236.collapse_all(it-it,VS.110).gifEsempio

Nell'esempio seguente viene modificato il primo esempio rendere la classe employee un tipo di valore.Questo tipo di valore viene quindi inserito solo in cliext::set come nel primo esempio.

// 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 si tenta di inserire un handle per un tipo di valore in un contenitore, Errore del compilatore C3225 viene generato.

Bb385236.collapse_all(it-it,VS.110).gifImplicazioni di memoria e prestazioni

È necessario considerare diversi fattori quando determina se utilizzare un handle ai tipi di riferimento o tipi di valore come elementi contenitore.Se si decide di utilizzare i tipi di valore, ricordare che una copia dell'elemento viene eseguita ogni volta in un elemento viene inserita nel contenitore.Per piccoli oggetti, non si deve essere un problema, ma se gli oggetti che vengono inseriti estesi, le prestazioni potrebbero che.Inoltre, se si utilizzano tipi di valore, è impossibile memorizzare un elemento nei contenitori più elementi perché ogni contenitore potrebbe avere la propria copia dell'elemento.

Se si decide di utilizzare un handle ai tipi di riferimento al contrario, le prestazioni possono aumentare in quanto non è necessario fare una copia dell'elemento quando vengono inserite nel contenitore.Inoltre, a differenza dei tipi di valore, lo stesso elemento può esistere in più contenitori.Tuttavia, se si decide di utilizzare l'handle, è necessario prestare particolare attenzione per assicurarsi che un handle siano valide e che l'oggetto a cui viene fatto riferimento non è stato eliminato in un altro punto del programma.

Problemi di proprietà con i contenitori

Contenitori di lavoro STL/CLR su semantica di valore.Ogni volta che viene inserito un elemento in un contenitore, una copia dell'elemento viene inserita.Se si desidera ottenere la semantica dei tipi di riferimento, è possibile inserire un handle a un oggetto anziché l'oggetto stesso.

Quando si chiama di evitare la presenza o deselezionare il metodo del contenitore degli oggetti di handle, gli oggetti che l'handle fanno riferimento non vengono liberati dalla memoria.È necessario o eliminare in modo esplicito l'oggetto, o, poiché questi oggetti si trovano nell'heap gestito, per consentire al Garbage Collector di liberare la memoria quando si determina che l'oggetto non viene più utilizzato.

Vedere anche

Riferimenti

Libreria di modelli standard