STL/CLR 库在标准 C++ 库中找到具有相同容器,但是,它在 .NET Framework 的托管环境中运行。如果您已熟悉标准模板库 (STL), STL/CLR 的最佳方式是继续使用已经开发,当升级您的代码以公共语言运行时的技能 (CLR)。
本文档提供在 STL/CLR 的容器概述,如容器元素的要求,您可以插入到容器中元素的类型,并且,所有权问题与容器的元素。在适当的时候,在本机标准模板库和 STL/CLR 之间的差异提到。
容器元素的要求
所有元素插入 STL 容器必须遵循某些准则。有关更多信息,请参见 STL/CLR容器元素的要求。
活动容器元素
STL/CLR 容器可以容纳元素的两种类型之一:
引用类型的句柄。
引用类型。
未装箱的值类型。
您不能插入装箱值类型到任何 STL/CLR 容器中。
引用类型的句柄
您可以插入句柄引用类型。 STL/CLR 容器中。面向 CLR 在 C++ 的句柄类似于在本机 C++ 的指针。有关更多信息,请参见 对象句柄运算符 (^)(C++ 组件扩展)。
示例
下面的示例演示如何插入的句柄。 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;
}
引用类型
也可能会插入每个引用类型 (而不是引用类型的句柄)。 STL/CLR 容器中。此处的主要区别在于,当容器引用类型时删除,析构函数为容器的所有元素对的调用。在引用类型的容器句柄,这些组件的析构函数不会调用。
示例
下面的示例演示如何插入一个 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;
}
未装箱的值类型
您还可以插入一个未装箱的值类型。 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 的容器处理值语义。在将元素插入到容器中,元素的副本插入时间。如果要获取类似于引用的语义,也可以插入句柄对象而不是对象。
当您调用清除或清除一个容器的方法处理对象时,处理引用的对象不会从内存中释放。则必须显式删除对象,或者,在中,因为这些对象位于托管堆,使垃圾回收器释放内存,一旦确定不再使用对象。