Контейнеры STL/CLR
Библиотека STL/CLR имеет те же контейнеры, которые находятся в стандартной библиотеке C++ C, но она выполняется в управляемую среду платформы .NET Framework. Если вы уже знакомы с библиотекой стандартных шаблонов (STL), STL/CLR лучшим способом продолжить использование навыками, уже разработано пока обновление кода к целевому объекту среды CLR (CLR).
В этом документе содержатся общие сведения о контейнеров в STL/CLR, например требования для элементов-контейнеров, типов элементов, которые можно добавлять в контейнеры и проблемы владения с элементами в контейнерах. При необходимости, разница между собственной библиотекой стандартных шаблонов и STL/CLR упомяните.
Требования для элементов контейнеров
Все элементы, добавленные в контейнеров STL должны подчиняться некоторым рекомендациям. Для получения дополнительной информации см. Требования к элементам контейнера STL/CLR.
Допустимые дочерние элементы
Контейнеры STL/CLR могут содержать один из 2 типов элементов.
Дескрипторы к ссылочным типам.
Ссылочные типы.
Две типы значения.
Нельзя типы значений упакованные вставкой в любые контейнеры STL/CLR.
Дескрипторы к ссылочным типам
Можно вставить дескриптор ссылочному типу в контейнер STL/CLR. Дескриптор в C++, на которую нацелен CLR аналогичн указатель в собственном C C++. Для получения дополнительной информации см. Оператор дескриптора объекта (^) (расширения компонентов C++).
Пример
В следующем примере показано, как вставить дескриптор объекта сотрудника в 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;
}
Ссылочные типы
Также можно вставить ссылочный тип (а не дескриптор ссылочному типу) в контейнер STL/CLR. Основное различие заключается в том, что когда контейнер ссылочных типов удален, деструктор вызывается для всех элементов, внутри контейнера. В контейнере дескрипторов к ссылочным типам, не были бы вызываются деструкторы для этих элементов.
Пример
В следующем примере показано, как вставить объект employees в 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;
}
Две типы значений
Можно также вставить неупакованный тип значения в контейнер STL/CLR. Неупакованный тип значения типа значения, не помещается в процессе в ссылочный тип.
Элемент типа значения может быть одним из стандартных типов значений, например int, или может быть определяемым пользователем типом значения, например value class. Дополнительные сведения см. в разделе Классы и структуры (расширения компонентов C++).
Пример
В следующем примере изменяется первый пример, выполнив классом сотрудника тип значения. Этот тип значения затем вставляется в 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 создается.
Влияние производительности и памяти
Следует учитывать несколько факторов, указывающее, использовать ли дескрипторы к ссылочным типам или типы значения как дочерние элементы. Если решено использовать типы значений, помните, что копия элемента выполняется каждый раз, когда элемент вставляется в контейнер. Для небольших объектов это не должно быть проблемой, но если, вставленные больших объектов, производительность может вытерпеть. Кроме того, при использовании типы значений, невозможно сохранить один элемент в нескольких контейнерах одновременно, так как каждый контейнер будет иметь собственную копию элемента.
Если решено использовать дескрипторы к ссылочным типам вместо, может повысить производительность, поскольку нет необходимости сделать копию элемента, когда она вставляется в контейнер. Кроме того, в отличие от типов значений, тот же элемент может существовать в нескольких контейнерах. Однако если решено использовать дескрипторов, необходимо соблюдать осторожность, чтобы гарантировать, что дескриптор допустим и что он указывает на объект не удаляется в любом другом месте программы.
Проблемы владения с контейнерами
Контейнеры в рабочем STL/CLR в семантике значение. Каждый раз при вставке элемента в контейнер, копия этого элемента будут. Если необходимо получить ссылку на похожую семантику, можно вставить дескриптор объекта, а не сам объект.
При вызове метода стираете очистка или контейнера объектов дескриптора, объекты, которые ссылаются на дескрипторы не удаляются из памяти. Необходимо либо явно удалять объект, поскольку эти объекты находятся в управляемой куче, позволяет сборщику мусора освободить память, как только он указывает, что объект больше не используется.