Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A Biblioteca STL/CLR consiste em contêineres semelhantes aos encontrados na Biblioteca Padrão do C++, mas é executada dentro do ambiente gerenciado do .NET Framework. Ele não é mantida atualizada com a Biblioteca Padrão C++ real e é mantida para suporte herdado.
Este documento fornece uma visão geral dos contêineres no STL/CLR, como os requisitos para elementos de contêiner, os tipos de elementos que você pode inserir nos contêineres e problemas de propriedade com os elementos nos contêineres. Quando apropriado, as diferenças entre a Biblioteca Padrão C++ nativa e STL/CLR são mencionadas.
Requisitos dos elementos de contêiner
Todos os elementos inseridos em contêineres STL/CLR devem obedecer a determinadas diretrizes. Para obter mais informações, consulte Requisitos para elementos contêiner STL/CLR.
Elementos contêiner válidos
Contêineres STL/CLR podem conter um dos dois tipos de elementos:
Manipula tipos de referência.
Tipos de referência.
Tipos de valor unboxed.
Você não pode inserir tipos de valor demarcado em nenhum dos contêineres STL/CLR.
Trata Tipos de referência
Você pode inserir um identificador para um tipo de referência em um contêiner STL/CLR. Um identificador no C++ direcionado ao CLR é análogo a um ponteiro no C++ nativo. Para obter mais informações, consulte Operador Handle to Object (^).
Exemplo
O exemplo a seguir mostra como inserir um identificador para um objeto Employee 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/CLR containers might require a public constructor, so it
// is a good idea to define one.
Employee() :
name(nullptr),
employeeNumber(0) { }
// All STL/CLR containers require a public copy constructor.
Employee(const Employee% orig) :
name(orig.name),
employeeNumber(orig.employeeNumber) { }
// All STL/CLR containers require a public assignment operator.
Employee% operator=(const Employee% orig)
{
if (this != %orig)
{
name = orig.name;
employeeNumber = orig.employeeNumber;
}
return *this;
}
// All STL/CLR 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;
}
Tipos 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 aqui é que, quando um contêiner de tipos de referência é excluído, o destruidor é chamado para todos os elementos dentro do contêiner. Em um contêiner de identificadores para tipos de referência, os destruidores desses elementos não seriam chamados.
Exemplo
O exemplo a seguir mostra como inserir um objeto Employee 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/CLR containers might require a public constructor, so it
// is a good idea to define one.
Employee() :
name(nullptr),
employeeNumber(0) { }
// All STL/CLR containers require a public copy constructor.
Employee(const Employee% orig) :
name(orig.name),
employeeNumber(orig.employeeNumber) { }
// All STL/CLR containers require a public assignment operator.
Employee% operator=(const Employee% orig)
{
if (this != %orig)
{
name = orig.name;
employeeNumber = orig.employeeNumber;
}
return *this;
}
// All STL/CLR 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;
}
Tipos de valor unboxed.
Você também pode inserir um tipo de valor unboxed em um contêiner STL/CLR. Um tipo de valor unboxed é um tipo de valor que não foi boxed 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 um value class. Para obter mais informações, consulte Classes e structs.
Exemplo
O exemplo a seguir modifica o primeiro exemplo, tornando a classe Employee um tipo de valor. Esse tipo de valor é inserido em um cliext::set exatamente 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 contêiner, o Erro do Compilador C3225 será gerado.
Implicações de desempenho e memória
Você deve considerar vários fatores ao determinar se deve usar identificadores para referenciar tipos ou tipos de valor como elementos contêiner. Se você decidir usar tipos de valor, lembre-se de que uma cópia do elemento é feita sempre que um elemento é inserido no contêiner. Para objetos pequenos, isso não deve ser um problema, mas se os objetos que estão sendo inseridos forem grandes, o desempenho poderá sofrer. 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 contêiner teria sua própria cópia do elemento.
Se você decidir usar identificadores para tipos de referência, o desempenho poderá aumentar porque não é necessário fazer uma cópia do elemento quando ele é inserido no contêiner. Além disso, ao contrário dos tipos de valor, o mesmo elemento pode existir em vários contêineres. No entanto, se você decidir usar identificadores, deverá ter cuidado para garantir que o identificador seja válido e que o objeto ao qual ele se refere não tenha sido excluído em outro lugar do programa.
Problemas de propriedade com contêineres
Os contêineres em STL/CLR funcionam pela semântica de valor. Toda vez que você insere um elemento em um contêiner, é inserida uma cópia desse elemento. Se você quiser obter semântica semelhante a referência, poderá inserir um identificador para um objeto em vez do objeto em si.
Quando você chama o método de limpar ou apagar de um contêiner de objetos de identificador, os objetos aos quais os identificadores se referem não são liberados da memória. Você deve excluir explicitamente o objeto ou, como esses objetos residem no heap gerenciado, permitir que o coletor de lixo libere a memória depois que ele determinar que o objeto não está mais sendo usado.