STL/CLR 容器
STL/CLR 程式庫有標準的 C++ 程式庫中找到的同一個容器,但受管理的環境中執行。NET Framework。如果您已經熟悉使用標準樣板程式庫 (STL),STL/CLR 會繼續使用您已經發展到目標通用語言執行階段 (CLR) 升級您的程式碼時使用的技術的最佳方式。
本文件提供在 STL/CLR 容器,例如容器項目,您可以在容器中,插入,且擁有權與容器中的項目會發出的項目類型的需求的概觀。在適當的地方所提及的原生的標準樣板程式庫和 STL/CLR 之間的差異。
容器項目的需求
所有的項目插入至 STL 容器必須遵循某些規定。如需詳細資訊,請參閱 STL/CLR 容器項目的需求。
有效容器項目
STL/CLR 容器可保存兩種類型的項目之一:
若要參考的型別會處理。
參考型別。
封裝的數值型別。
您無法插入 boxed 實值型別的任何 STL/CLR 容器。
參考型別控制代碼
您可以插入 STL/CLR 容器的參考型別控制代碼。以 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 容器中的參考型別 (而不是參考型別控制代碼)。最主要的差異是參考型別的容器刪除時,該容器內的所有項目的呼叫解構函式。在容器中的參考型別控制代碼,就不會呼叫解構函式,這些元素。
範例
下列範例顯示如何插入員工物件到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;
}
Unboxed 的數值型別
您也可以插入的數值型別 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 容器處理實值語意。每當您將項目插入容器時,會分別插入該項目的複本。如果您想要取得參考類似的語意時,您可以插入一個物件,而不是物件本身的控制代碼。
當您呼叫清除,或清除一個容器的控制代碼物件的方法時,控點,請參閱物件未被釋放的記憶體。您必須明確地刪除物件,或者,因為這些物件是在 managed 堆積,可讓記憶體回收行程釋放記憶體之後,它會判斷無法再使用該物件。